Home | History | Annotate | Line # | Download | only in dist
      1  1.1     alc /*
      2  1.1     alc  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
      3  1.1     alc  * Copyright (c) 2002-2008 Atheros Communications, Inc.
      4  1.1     alc  *
      5  1.1     alc  * Permission to use, copy, modify, and/or distribute this software for any
      6  1.1     alc  * purpose with or without fee is hereby granted, provided that the above
      7  1.1     alc  * copyright notice and this permission notice appear in all copies.
      8  1.1     alc  *
      9  1.1     alc  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  1.1     alc  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  1.1     alc  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  1.1     alc  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  1.1     alc  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  1.1     alc  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  1.1     alc  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  1.1     alc  *
     17  1.3  cegger  * $Id: ah.c,v 1.3 2011/03/07 11:25:42 cegger Exp $
     18  1.1     alc  */
     19  1.1     alc #include "opt_ah.h"
     20  1.1     alc 
     21  1.1     alc #include "ah.h"
     22  1.1     alc #include "ah_internal.h"
     23  1.1     alc #include "ah_devid.h"
     24  1.1     alc 
     25  1.1     alc /* linker set of registered chips */
     26  1.1     alc OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
     27  1.1     alc 
     28  1.1     alc /*
     29  1.1     alc  * Check the set of registered chips to see if any recognize
     30  1.1     alc  * the device as one they can support.
     31  1.1     alc  */
     32  1.1     alc const char*
     33  1.1     alc ath_hal_probe(uint16_t vendorid, uint16_t devid)
     34  1.1     alc {
     35  1.2     alc 	struct ath_hal_chip * const *pchip;
     36  1.1     alc 
     37  1.1     alc 	OS_SET_FOREACH(pchip, ah_chips) {
     38  1.1     alc 		const char *name = (*pchip)->probe(vendorid, devid);
     39  1.1     alc 		if (name != AH_NULL)
     40  1.1     alc 			return name;
     41  1.1     alc 	}
     42  1.1     alc 	return AH_NULL;
     43  1.1     alc }
     44  1.1     alc 
     45  1.1     alc /*
     46  1.1     alc  * Attach detects device chip revisions, initializes the hwLayer
     47  1.1     alc  * function list, reads EEPROM information,
     48  1.1     alc  * selects reset vectors, and performs a short self test.
     49  1.1     alc  * Any failures will return an error that should cause a hardware
     50  1.1     alc  * disable.
     51  1.1     alc  */
     52  1.1     alc struct ath_hal*
     53  1.1     alc ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
     54  1.1     alc 	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
     55  1.1     alc {
     56  1.2     alc 	struct ath_hal_chip * const *pchip;
     57  1.1     alc 
     58  1.1     alc 	OS_SET_FOREACH(pchip, ah_chips) {
     59  1.1     alc 		struct ath_hal_chip *chip = *pchip;
     60  1.1     alc 		struct ath_hal *ah;
     61  1.1     alc 
     62  1.1     alc 		/* XXX don't have vendorid, assume atheros one works */
     63  1.1     alc 		if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
     64  1.1     alc 			continue;
     65  1.1     alc 		ah = chip->attach(devid, sc, st, sh, error);
     66  1.1     alc 		if (ah != AH_NULL) {
     67  1.1     alc 			/* copy back private state to public area */
     68  1.1     alc 			ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
     69  1.1     alc 			ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
     70  1.1     alc 			ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
     71  1.1     alc 			ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
     72  1.1     alc 			ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
     73  1.1     alc 			ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
     74  1.1     alc 			ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
     75  1.1     alc 			return ah;
     76  1.1     alc 		}
     77  1.1     alc 	}
     78  1.1     alc 	return AH_NULL;
     79  1.1     alc }
     80  1.1     alc 
     81  1.1     alc /* linker set of registered RF backends */
     82  1.1     alc OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
     83  1.1     alc 
     84  1.1     alc /*
     85  1.1     alc  * Check the set of registered RF backends to see if
     86  1.1     alc  * any recognize the device as one they can support.
     87  1.1     alc  */
     88  1.1     alc struct ath_hal_rf *
     89  1.1     alc ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
     90  1.1     alc {
     91  1.2     alc #ifdef AH_HAS_RF
     92  1.2     alc 	struct ath_hal_rf * const *prf;
     93  1.1     alc 
     94  1.1     alc 	OS_SET_FOREACH(prf, ah_rfs) {
     95  1.1     alc 		struct ath_hal_rf *rf = *prf;
     96  1.1     alc 		if (rf->probe(ah))
     97  1.1     alc 			return rf;
     98  1.1     alc 	}
     99  1.1     alc 	*ecode = HAL_ENOTSUPP;
    100  1.2     alc #endif
    101  1.1     alc 	return AH_NULL;
    102  1.1     alc }
    103  1.1     alc 
    104  1.1     alc /*
    105  1.1     alc  * Poll the register looking for a specific value.
    106  1.1     alc  */
    107  1.1     alc HAL_BOOL
    108  1.1     alc ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
    109  1.1     alc {
    110  1.1     alc #define	AH_TIMEOUT	1000
    111  1.1     alc 	int i;
    112  1.1     alc 
    113  1.1     alc 	for (i = 0; i < AH_TIMEOUT; i++) {
    114  1.1     alc 		if ((OS_REG_READ(ah, reg) & mask) == val)
    115  1.1     alc 			return AH_TRUE;
    116  1.1     alc 		OS_DELAY(10);
    117  1.1     alc 	}
    118  1.1     alc 	HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
    119  1.1     alc 	    "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
    120  1.1     alc 	    __func__, reg, OS_REG_READ(ah, reg), mask, val);
    121  1.1     alc 	return AH_FALSE;
    122  1.1     alc #undef AH_TIMEOUT
    123  1.1     alc }
    124  1.1     alc 
    125  1.1     alc /*
    126  1.1     alc  * Reverse the bits starting at the low bit for a value of
    127  1.1     alc  * bit_count in size
    128  1.1     alc  */
    129  1.1     alc uint32_t
    130  1.1     alc ath_hal_reverseBits(uint32_t val, uint32_t n)
    131  1.1     alc {
    132  1.1     alc 	uint32_t retval;
    133  1.1     alc 	int i;
    134  1.1     alc 
    135  1.1     alc 	for (i = 0, retval = 0; i < n; i++) {
    136  1.1     alc 		retval = (retval << 1) | (val & 1);
    137  1.1     alc 		val >>= 1;
    138  1.1     alc 	}
    139  1.1     alc 	return retval;
    140  1.1     alc }
    141  1.1     alc 
    142  1.1     alc /*
    143  1.1     alc  * Compute the time to transmit a frame of length frameLen bytes
    144  1.1     alc  * using the specified rate, phy, and short preamble setting.
    145  1.1     alc  */
    146  1.1     alc uint16_t
    147  1.1     alc ath_hal_computetxtime(struct ath_hal *ah,
    148  1.1     alc 	const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
    149  1.1     alc 	HAL_BOOL shortPreamble)
    150  1.1     alc {
    151  1.1     alc 	uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
    152  1.1     alc 	uint32_t kbps;
    153  1.1     alc 
    154  1.1     alc 	kbps = rates->info[rateix].rateKbps;
    155  1.1     alc 	/*
    156  1.1     alc 	 * index can be invalid duting dynamic Turbo transitions.
    157  1.1     alc 	 */
    158  1.1     alc 	if(kbps == 0) return 0;
    159  1.1     alc 	switch (rates->info[rateix].phy) {
    160  1.1     alc 
    161  1.1     alc 	case IEEE80211_T_CCK:
    162  1.1     alc #define CCK_SIFS_TIME        10
    163  1.1     alc #define CCK_PREAMBLE_BITS   144
    164  1.1     alc #define CCK_PLCP_BITS        48
    165  1.1     alc 		phyTime		= CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
    166  1.1     alc 		if (shortPreamble && rates->info[rateix].shortPreamble)
    167  1.1     alc 			phyTime >>= 1;
    168  1.1     alc 		numBits		= frameLen << 3;
    169  1.1     alc 		txTime		= CCK_SIFS_TIME + phyTime
    170  1.1     alc 				+ ((numBits * 1000)/kbps);
    171  1.1     alc 		break;
    172  1.1     alc #undef CCK_SIFS_TIME
    173  1.1     alc #undef CCK_PREAMBLE_BITS
    174  1.1     alc #undef CCK_PLCP_BITS
    175  1.1     alc 
    176  1.1     alc 	case IEEE80211_T_OFDM:
    177  1.1     alc #define OFDM_SIFS_TIME        16
    178  1.1     alc #define OFDM_PREAMBLE_TIME    20
    179  1.1     alc #define OFDM_PLCP_BITS        22
    180  1.1     alc #define OFDM_SYMBOL_TIME       4
    181  1.1     alc 
    182  1.1     alc #define OFDM_SIFS_TIME_HALF	32
    183  1.1     alc #define OFDM_PREAMBLE_TIME_HALF	40
    184  1.1     alc #define OFDM_PLCP_BITS_HALF	22
    185  1.1     alc #define OFDM_SYMBOL_TIME_HALF	8
    186  1.1     alc 
    187  1.1     alc #define OFDM_SIFS_TIME_QUARTER 		64
    188  1.1     alc #define OFDM_PREAMBLE_TIME_QUARTER	80
    189  1.1     alc #define OFDM_PLCP_BITS_QUARTER		22
    190  1.1     alc #define OFDM_SYMBOL_TIME_QUARTER	16
    191  1.1     alc 
    192  1.1     alc 		if (AH_PRIVATE(ah)->ah_curchan &&
    193  1.1     alc 			IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
    194  1.1     alc 			bitsPerSymbol	= (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
    195  1.1     alc 			HALASSERT(bitsPerSymbol != 0);
    196  1.1     alc 
    197  1.1     alc 			numBits		= OFDM_PLCP_BITS + (frameLen << 3);
    198  1.1     alc 			numSymbols	= howmany(numBits, bitsPerSymbol);
    199  1.1     alc 			txTime		= OFDM_SIFS_TIME_QUARTER
    200  1.1     alc 						+ OFDM_PREAMBLE_TIME_QUARTER
    201  1.1     alc 					+ (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
    202  1.1     alc 		} else if (AH_PRIVATE(ah)->ah_curchan &&
    203  1.1     alc 				IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
    204  1.1     alc 			bitsPerSymbol	= (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
    205  1.1     alc 			HALASSERT(bitsPerSymbol != 0);
    206  1.1     alc 
    207  1.1     alc 			numBits		= OFDM_PLCP_BITS + (frameLen << 3);
    208  1.1     alc 			numSymbols	= howmany(numBits, bitsPerSymbol);
    209  1.1     alc 			txTime		= OFDM_SIFS_TIME_HALF +
    210  1.1     alc 						OFDM_PREAMBLE_TIME_HALF
    211  1.1     alc 					+ (numSymbols * OFDM_SYMBOL_TIME_HALF);
    212  1.1     alc 		} else { /* full rate channel */
    213  1.1     alc 			bitsPerSymbol	= (kbps * OFDM_SYMBOL_TIME) / 1000;
    214  1.1     alc 			HALASSERT(bitsPerSymbol != 0);
    215  1.1     alc 
    216  1.1     alc 			numBits		= OFDM_PLCP_BITS + (frameLen << 3);
    217  1.1     alc 			numSymbols	= howmany(numBits, bitsPerSymbol);
    218  1.1     alc 			txTime		= OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
    219  1.1     alc 					+ (numSymbols * OFDM_SYMBOL_TIME);
    220  1.1     alc 		}
    221  1.1     alc 		break;
    222  1.1     alc 
    223  1.1     alc #undef OFDM_SIFS_TIME
    224  1.1     alc #undef OFDM_PREAMBLE_TIME
    225  1.1     alc #undef OFDM_PLCP_BITS
    226  1.1     alc #undef OFDM_SYMBOL_TIME
    227  1.1     alc 
    228  1.1     alc 	case IEEE80211_T_TURBO:
    229  1.1     alc #define TURBO_SIFS_TIME         8
    230  1.1     alc #define TURBO_PREAMBLE_TIME    14
    231  1.1     alc #define TURBO_PLCP_BITS        22
    232  1.1     alc #define TURBO_SYMBOL_TIME       4
    233  1.1     alc 		/* we still save OFDM rates in kbps - so double them */
    234  1.1     alc 		bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
    235  1.1     alc 		HALASSERT(bitsPerSymbol != 0);
    236  1.1     alc 
    237  1.1     alc 		numBits       = TURBO_PLCP_BITS + (frameLen << 3);
    238  1.1     alc 		numSymbols    = howmany(numBits, bitsPerSymbol);
    239  1.1     alc 		txTime        = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME
    240  1.1     alc 			      + (numSymbols * TURBO_SYMBOL_TIME);
    241  1.1     alc 		break;
    242  1.1     alc #undef TURBO_SIFS_TIME
    243  1.1     alc #undef TURBO_PREAMBLE_TIME
    244  1.1     alc #undef TURBO_PLCP_BITS
    245  1.1     alc #undef TURBO_SYMBOL_TIME
    246  1.1     alc 
    247  1.1     alc 	default:
    248  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_PHYIO,
    249  1.1     alc 		    "%s: unknown phy %u (rate ix %u)\n",
    250  1.1     alc 		    __func__, rates->info[rateix].phy, rateix);
    251  1.1     alc 		txTime = 0;
    252  1.1     alc 		break;
    253  1.1     alc 	}
    254  1.1     alc 	return txTime;
    255  1.1     alc }
    256  1.1     alc 
    257  1.1     alc static __inline int
    258  1.1     alc mapgsm(u_int freq, u_int flags)
    259  1.1     alc {
    260  1.1     alc 	freq *= 10;
    261  1.1     alc 	if (flags & CHANNEL_QUARTER)
    262  1.1     alc 		freq += 5;
    263  1.1     alc 	else if (flags & CHANNEL_HALF)
    264  1.1     alc 		freq += 10;
    265  1.1     alc 	else
    266  1.1     alc 		freq += 20;
    267  1.1     alc 	return (freq - 24220) / 5;
    268  1.1     alc }
    269  1.1     alc 
    270  1.1     alc static __inline int
    271  1.1     alc mappsb(u_int freq, u_int flags)
    272  1.1     alc {
    273  1.1     alc 	return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
    274  1.1     alc }
    275  1.1     alc 
    276  1.1     alc /*
    277  1.1     alc  * Convert GHz frequency to IEEE channel number.
    278  1.1     alc  */
    279  1.1     alc int
    280  1.1     alc ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags)
    281  1.1     alc {
    282  1.1     alc 	if (flags & CHANNEL_2GHZ) {	/* 2GHz band */
    283  1.1     alc 		if (freq == 2484)
    284  1.1     alc 			return 14;
    285  1.1     alc 		if (freq < 2484) {
    286  1.1     alc 			if (ath_hal_isgsmsku(ah))
    287  1.1     alc 				return mapgsm(freq, flags);
    288  1.1     alc 			return ((int)freq - 2407) / 5;
    289  1.1     alc 		} else
    290  1.1     alc 			return 15 + ((freq - 2512) / 20);
    291  1.1     alc 	} else if (flags & CHANNEL_5GHZ) {/* 5Ghz band */
    292  1.1     alc 		if (ath_hal_ispublicsafetysku(ah) &&
    293  1.1     alc 		    IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
    294  1.1     alc 			return mappsb(freq, flags);
    295  1.1     alc 		} else if ((flags & CHANNEL_A) && (freq <= 5000)) {
    296  1.1     alc 			return (freq - 4000) / 5;
    297  1.1     alc 		} else {
    298  1.1     alc 			return (freq - 5000) / 5;
    299  1.1     alc 		}
    300  1.1     alc 	} else {			/* either, guess */
    301  1.1     alc 		if (freq == 2484)
    302  1.1     alc 			return 14;
    303  1.1     alc 		if (freq < 2484) {
    304  1.1     alc 			if (ath_hal_isgsmsku(ah))
    305  1.1     alc 				return mapgsm(freq, flags);
    306  1.1     alc 			return ((int)freq - 2407) / 5;
    307  1.1     alc 		}
    308  1.1     alc 		if (freq < 5000) {
    309  1.1     alc 			if (ath_hal_ispublicsafetysku(ah) &&
    310  1.1     alc 			    IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
    311  1.1     alc 				return mappsb(freq, flags);
    312  1.1     alc 			} else if (freq > 4900) {
    313  1.1     alc 				return (freq - 4000) / 5;
    314  1.1     alc 			} else {
    315  1.1     alc 				return 15 + ((freq - 2512) / 20);
    316  1.1     alc 			}
    317  1.1     alc 		}
    318  1.1     alc 		return (freq - 5000) / 5;
    319  1.1     alc 	}
    320  1.1     alc }
    321  1.1     alc 
    322  1.1     alc typedef enum {
    323  1.1     alc 	WIRELESS_MODE_11a   = 0,
    324  1.1     alc 	WIRELESS_MODE_TURBO = 1,
    325  1.1     alc 	WIRELESS_MODE_11b   = 2,
    326  1.1     alc 	WIRELESS_MODE_11g   = 3,
    327  1.1     alc 	WIRELESS_MODE_108g  = 4,
    328  1.1     alc 
    329  1.1     alc 	WIRELESS_MODE_MAX
    330  1.1     alc } WIRELESS_MODE;
    331  1.1     alc 
    332  1.1     alc static WIRELESS_MODE
    333  1.1     alc ath_hal_chan2wmode(struct ath_hal *ah, const HAL_CHANNEL *chan)
    334  1.1     alc {
    335  1.1     alc 	if (IS_CHAN_CCK(chan))
    336  1.1     alc 		return WIRELESS_MODE_11b;
    337  1.1     alc 	if (IS_CHAN_G(chan))
    338  1.1     alc 		return WIRELESS_MODE_11g;
    339  1.1     alc 	if (IS_CHAN_108G(chan))
    340  1.1     alc 		return WIRELESS_MODE_108g;
    341  1.1     alc 	if (IS_CHAN_TURBO(chan))
    342  1.1     alc 		return WIRELESS_MODE_TURBO;
    343  1.1     alc 	return WIRELESS_MODE_11a;
    344  1.1     alc }
    345  1.1     alc 
    346  1.1     alc /*
    347  1.1     alc  * Convert between microseconds and core system clocks.
    348  1.1     alc  */
    349  1.1     alc                                      /* 11a Turbo  11b  11g  108g */
    350  1.1     alc static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
    351  1.1     alc 
    352  1.1     alc u_int
    353  1.1     alc ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
    354  1.1     alc {
    355  1.1     alc 	const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
    356  1.1     alc 	u_int clks;
    357  1.1     alc 
    358  1.1     alc 	/* NB: ah_curchan may be null when called attach time */
    359  1.1     alc 	if (c != AH_NULL) {
    360  1.1     alc 		clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
    361  1.1     alc 		if (IS_CHAN_HT40(c))
    362  1.1     alc 			clks <<= 1;
    363  1.1     alc 		else if (IS_CHAN_HALF_RATE(c))
    364  1.1     alc 			clks >>= 1;
    365  1.1     alc 		else if (IS_CHAN_QUARTER_RATE(c))
    366  1.1     alc 			clks >>= 2;
    367  1.1     alc 	} else
    368  1.1     alc 		clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
    369  1.1     alc 	return clks;
    370  1.1     alc }
    371  1.1     alc 
    372  1.1     alc u_int
    373  1.1     alc ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
    374  1.1     alc {
    375  1.1     alc 	const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
    376  1.1     alc 	u_int usec;
    377  1.1     alc 
    378  1.1     alc 	/* NB: ah_curchan may be null when called attach time */
    379  1.1     alc 	if (c != AH_NULL) {
    380  1.1     alc 		usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
    381  1.1     alc 		if (IS_CHAN_HT40(c))
    382  1.1     alc 			usec >>= 1;
    383  1.1     alc 		else if (IS_CHAN_HALF_RATE(c))
    384  1.1     alc 			usec <<= 1;
    385  1.1     alc 		else if (IS_CHAN_QUARTER_RATE(c))
    386  1.1     alc 			usec <<= 2;
    387  1.1     alc 	} else
    388  1.1     alc 		usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
    389  1.1     alc 	return usec;
    390  1.1     alc }
    391  1.1     alc 
    392  1.1     alc /*
    393  1.1     alc  * Setup a h/w rate table's reverse lookup table and
    394  1.1     alc  * fill in ack durations.  This routine is called for
    395  1.1     alc  * each rate table returned through the ah_getRateTable
    396  1.1     alc  * method.  The reverse lookup tables are assumed to be
    397  1.1     alc  * initialized to zero (or at least the first entry).
    398  1.1     alc  * We use this as a key that indicates whether or not
    399  1.1     alc  * we've previously setup the reverse lookup table.
    400  1.1     alc  *
    401  1.1     alc  * XXX not reentrant, but shouldn't matter
    402  1.1     alc  */
    403  1.1     alc void
    404  1.1     alc ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
    405  1.1     alc {
    406  1.1     alc #define	N(a)	(sizeof(a)/sizeof(a[0]))
    407  1.1     alc 	int i;
    408  1.1     alc 
    409  1.1     alc 	if (rt->rateCodeToIndex[0] != 0)	/* already setup */
    410  1.1     alc 		return;
    411  1.1     alc 	for (i = 0; i < N(rt->rateCodeToIndex); i++)
    412  1.1     alc 		rt->rateCodeToIndex[i] = (uint8_t) -1;
    413  1.1     alc 	for (i = 0; i < rt->rateCount; i++) {
    414  1.1     alc 		uint8_t code = rt->info[i].rateCode;
    415  1.1     alc 		uint8_t cix = rt->info[i].controlRate;
    416  1.1     alc 
    417  1.1     alc 		HALASSERT(code < N(rt->rateCodeToIndex));
    418  1.1     alc 		rt->rateCodeToIndex[code] = i;
    419  1.1     alc 		HALASSERT((code | rt->info[i].shortPreamble) <
    420  1.1     alc 		    N(rt->rateCodeToIndex));
    421  1.1     alc 		rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
    422  1.1     alc 		/*
    423  1.1     alc 		 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
    424  1.1     alc 		 *     depends on whether they are marked as basic rates;
    425  1.1     alc 		 *     the static tables are setup with an 11b-compatible
    426  1.1     alc 		 *     2Mb/s rate which will work but is suboptimal
    427  1.1     alc 		 */
    428  1.1     alc 		rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
    429  1.1     alc 			WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
    430  1.1     alc 		rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
    431  1.1     alc 			WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
    432  1.1     alc 	}
    433  1.1     alc #undef N
    434  1.1     alc }
    435  1.1     alc 
    436  1.1     alc HAL_STATUS
    437  1.1     alc ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
    438  1.1     alc 	uint32_t capability, uint32_t *result)
    439  1.1     alc {
    440  1.1     alc 	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
    441  1.1     alc 
    442  1.1     alc 	switch (type) {
    443  1.1     alc 	case HAL_CAP_REG_DMN:		/* regulatory domain */
    444  1.1     alc 		*result = AH_PRIVATE(ah)->ah_currentRD;
    445  1.1     alc 		return HAL_OK;
    446  1.1     alc 	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
    447  1.1     alc 	case HAL_CAP_TKIP_MIC:		/* handle TKIP MIC in hardware */
    448  1.1     alc 		return HAL_ENOTSUPP;
    449  1.1     alc 	case HAL_CAP_TKIP_SPLIT:	/* hardware TKIP uses split keys */
    450  1.1     alc 		return HAL_ENOTSUPP;
    451  1.1     alc 	case HAL_CAP_PHYCOUNTERS:	/* hardware PHY error counters */
    452  1.1     alc 		return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
    453  1.1     alc 	case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
    454  1.1     alc 		return HAL_ENOTSUPP;
    455  1.1     alc 	case HAL_CAP_DIVERSITY:		/* hardware supports fast diversity */
    456  1.1     alc 		return HAL_ENOTSUPP;
    457  1.1     alc 	case HAL_CAP_KEYCACHE_SIZE:	/* hardware key cache size */
    458  1.1     alc 		*result =  pCap->halKeyCacheSize;
    459  1.1     alc 		return HAL_OK;
    460  1.1     alc 	case HAL_CAP_NUM_TXQUEUES:	/* number of hardware tx queues */
    461  1.1     alc 		*result = pCap->halTotalQueues;
    462  1.1     alc 		return HAL_OK;
    463  1.1     alc 	case HAL_CAP_VEOL:		/* hardware supports virtual EOL */
    464  1.1     alc 		return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
    465  1.1     alc 	case HAL_CAP_PSPOLL:		/* hardware PS-Poll support works */
    466  1.1     alc 		return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
    467  1.1     alc 	case HAL_CAP_COMPRESSION:
    468  1.1     alc 		return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
    469  1.1     alc 	case HAL_CAP_BURST:
    470  1.1     alc 		return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
    471  1.1     alc 	case HAL_CAP_FASTFRAME:
    472  1.1     alc 		return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
    473  1.1     alc 	case HAL_CAP_DIAG:		/* hardware diagnostic support */
    474  1.1     alc 		*result = AH_PRIVATE(ah)->ah_diagreg;
    475  1.1     alc 		return HAL_OK;
    476  1.1     alc 	case HAL_CAP_TXPOW:		/* global tx power limit  */
    477  1.1     alc 		switch (capability) {
    478  1.1     alc 		case 0:			/* facility is supported */
    479  1.1     alc 			return HAL_OK;
    480  1.1     alc 		case 1:			/* current limit */
    481  1.1     alc 			*result = AH_PRIVATE(ah)->ah_powerLimit;
    482  1.1     alc 			return HAL_OK;
    483  1.1     alc 		case 2:			/* current max tx power */
    484  1.1     alc 			*result = AH_PRIVATE(ah)->ah_maxPowerLevel;
    485  1.1     alc 			return HAL_OK;
    486  1.1     alc 		case 3:			/* scale factor */
    487  1.1     alc 			*result = AH_PRIVATE(ah)->ah_tpScale;
    488  1.1     alc 			return HAL_OK;
    489  1.1     alc 		}
    490  1.1     alc 		return HAL_ENOTSUPP;
    491  1.1     alc 	case HAL_CAP_BSSIDMASK:		/* hardware supports bssid mask */
    492  1.1     alc 		return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
    493  1.1     alc 	case HAL_CAP_MCAST_KEYSRCH:	/* multicast frame keycache search */
    494  1.1     alc 		return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
    495  1.1     alc 	case HAL_CAP_TSF_ADJUST:	/* hardware has beacon tsf adjust */
    496  1.1     alc 		return HAL_ENOTSUPP;
    497  1.1     alc 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
    498  1.1     alc 		switch (capability) {
    499  1.1     alc 		case 0:			/* facility is supported */
    500  1.1     alc 			return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
    501  1.1     alc 		case 1:			/* current setting */
    502  1.1     alc 			return AH_PRIVATE(ah)->ah_rfkillEnabled ?
    503  1.1     alc 				HAL_OK : HAL_ENOTSUPP;
    504  1.1     alc 		case 2:			/* rfsilent config */
    505  1.1     alc 			*result = AH_PRIVATE(ah)->ah_rfsilent;
    506  1.1     alc 			return HAL_OK;
    507  1.1     alc 		}
    508  1.1     alc 		return HAL_ENOTSUPP;
    509  1.1     alc 	case HAL_CAP_11D:
    510  1.1     alc #ifdef AH_SUPPORT_11D
    511  1.1     alc 		return HAL_OK;
    512  1.1     alc #else
    513  1.1     alc 		return HAL_ENOTSUPP;
    514  1.1     alc #endif
    515  1.1     alc 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
    516  1.1     alc 		return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
    517  1.1     alc 	case HAL_CAP_HT:
    518  1.1     alc 		return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
    519  1.1     alc 	case HAL_CAP_TX_CHAINMASK:	/* mask of TX chains supported */
    520  1.1     alc 		*result = pCap->halTxChainMask;
    521  1.1     alc 		return HAL_OK;
    522  1.1     alc 	case HAL_CAP_RX_CHAINMASK:	/* mask of RX chains supported */
    523  1.1     alc 		*result = pCap->halRxChainMask;
    524  1.1     alc 		return HAL_OK;
    525  1.1     alc 	case HAL_CAP_RXTSTAMP_PREC:	/* rx desc tstamp precision (bits) */
    526  1.1     alc 		*result = pCap->halTstampPrecision;
    527  1.1     alc 		return HAL_OK;
    528  1.3  cegger 	case HAL_CAP_INTRMASK:		/* mask of supported interrupts */
    529  1.3  cegger 		*result = pCap->halIntrMask;
    530  1.3  cegger 		return HAL_OK;
    531  1.3  cegger 	case HAL_CAP_BSSIDMATCH:	/* hardware has disable bssid match */
    532  1.3  cegger 		return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
    533  1.1     alc 	default:
    534  1.1     alc 		return HAL_EINVAL;
    535  1.1     alc 	}
    536  1.1     alc }
    537  1.1     alc 
    538  1.1     alc HAL_BOOL
    539  1.1     alc ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
    540  1.1     alc 	uint32_t capability, uint32_t setting, HAL_STATUS *status)
    541  1.1     alc {
    542  1.1     alc 
    543  1.1     alc 	switch (type) {
    544  1.1     alc 	case HAL_CAP_TXPOW:
    545  1.1     alc 		switch (capability) {
    546  1.1     alc 		case 3:
    547  1.1     alc 			if (setting <= HAL_TP_SCALE_MIN) {
    548  1.1     alc 				AH_PRIVATE(ah)->ah_tpScale = setting;
    549  1.1     alc 				return AH_TRUE;
    550  1.1     alc 			}
    551  1.1     alc 			break;
    552  1.1     alc 		}
    553  1.1     alc 		break;
    554  1.1     alc 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
    555  1.1     alc 		/*
    556  1.1     alc 		 * NB: allow even if halRfSilentSupport is false
    557  1.1     alc 		 *     in case the EEPROM is misprogrammed.
    558  1.1     alc 		 */
    559  1.1     alc 		switch (capability) {
    560  1.1     alc 		case 1:			/* current setting */
    561  1.1     alc 			AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
    562  1.1     alc 			return AH_TRUE;
    563  1.1     alc 		case 2:			/* rfsilent config */
    564  1.1     alc 			/* XXX better done per-chip for validation? */
    565  1.1     alc 			AH_PRIVATE(ah)->ah_rfsilent = setting;
    566  1.1     alc 			return AH_TRUE;
    567  1.1     alc 		}
    568  1.1     alc 		break;
    569  1.1     alc 	case HAL_CAP_REG_DMN:		/* regulatory domain */
    570  1.1     alc 		AH_PRIVATE(ah)->ah_currentRD = setting;
    571  1.1     alc 		return AH_TRUE;
    572  1.1     alc 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
    573  1.1     alc 		AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
    574  1.1     alc 		return AH_TRUE;
    575  1.1     alc 	default:
    576  1.1     alc 		break;
    577  1.1     alc 	}
    578  1.1     alc 	if (status)
    579  1.1     alc 		*status = HAL_EINVAL;
    580  1.1     alc 	return AH_FALSE;
    581  1.1     alc }
    582  1.1     alc 
    583  1.1     alc /*
    584  1.1     alc  * Common support for getDiagState method.
    585  1.1     alc  */
    586  1.1     alc 
    587  1.1     alc static u_int
    588  1.1     alc ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
    589  1.1     alc 	void *dstbuf, int space)
    590  1.1     alc {
    591  1.1     alc 	uint32_t *dp = dstbuf;
    592  1.1     alc 	int i;
    593  1.1     alc 
    594  1.1     alc 	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
    595  1.1     alc 		u_int r = regs[i].start;
    596  1.1     alc 		u_int e = regs[i].end;
    597  1.1     alc 		*dp++ = (r<<16) | e;
    598  1.1     alc 		space -= sizeof(uint32_t);
    599  1.1     alc 		do {
    600  1.1     alc 			*dp++ = OS_REG_READ(ah, r);
    601  1.1     alc 			r += sizeof(uint32_t);
    602  1.1     alc 			space -= sizeof(uint32_t);
    603  1.1     alc 		} while (r <= e && space >= sizeof(uint32_t));
    604  1.1     alc 	}
    605  1.1     alc 	return (char *) dp - (char *) dstbuf;
    606  1.1     alc }
    607  1.1     alc 
    608  1.1     alc HAL_BOOL
    609  1.1     alc ath_hal_getdiagstate(struct ath_hal *ah, int request,
    610  1.1     alc 	const void *args, uint32_t argsize,
    611  1.1     alc 	void **result, uint32_t *resultsize)
    612  1.1     alc {
    613  1.1     alc 	switch (request) {
    614  1.1     alc 	case HAL_DIAG_REVS:
    615  1.1     alc 		*result = &AH_PRIVATE(ah)->ah_devid;
    616  1.1     alc 		*resultsize = sizeof(HAL_REVS);
    617  1.1     alc 		return AH_TRUE;
    618  1.1     alc 	case HAL_DIAG_REGS:
    619  1.1     alc 		*resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
    620  1.1     alc 		return AH_TRUE;
    621  1.1     alc 	case HAL_DIAG_FATALERR:
    622  1.1     alc 		*result = &AH_PRIVATE(ah)->ah_fatalState[0];
    623  1.1     alc 		*resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
    624  1.1     alc 		return AH_TRUE;
    625  1.1     alc 	case HAL_DIAG_EEREAD:
    626  1.1     alc 		if (argsize != sizeof(uint16_t))
    627  1.1     alc 			return AH_FALSE;
    628  1.1     alc 		if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
    629  1.1     alc 			return AH_FALSE;
    630  1.1     alc 		*resultsize = sizeof(uint16_t);
    631  1.1     alc 		return AH_TRUE;
    632  1.1     alc #ifdef AH_PRIVATE_DIAG
    633  1.1     alc 	case HAL_DIAG_SETKEY: {
    634  1.1     alc 		const HAL_DIAG_KEYVAL *dk;
    635  1.1     alc 
    636  1.1     alc 		if (argsize != sizeof(HAL_DIAG_KEYVAL))
    637  1.1     alc 			return AH_FALSE;
    638  1.1     alc 		dk = (const HAL_DIAG_KEYVAL *)args;
    639  1.1     alc 		return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
    640  1.1     alc 			&dk->dk_keyval, dk->dk_mac, dk->dk_xor);
    641  1.1     alc 	}
    642  1.1     alc 	case HAL_DIAG_RESETKEY:
    643  1.1     alc 		if (argsize != sizeof(uint16_t))
    644  1.1     alc 			return AH_FALSE;
    645  1.1     alc 		return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
    646  1.1     alc #ifdef AH_SUPPORT_WRITE_EEPROM
    647  1.1     alc 	case HAL_DIAG_EEWRITE: {
    648  1.1     alc 		const HAL_DIAG_EEVAL *ee;
    649  1.1     alc 		if (argsize != sizeof(HAL_DIAG_EEVAL))
    650  1.1     alc 			return AH_FALSE;
    651  1.1     alc 		ee = (const HAL_DIAG_EEVAL *)args;
    652  1.1     alc 		return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
    653  1.1     alc 	}
    654  1.1     alc #endif /* AH_SUPPORT_WRITE_EEPROM */
    655  1.1     alc #endif /* AH_PRIVATE_DIAG */
    656  1.1     alc 	case HAL_DIAG_11NCOMPAT:
    657  1.1     alc 		if (argsize == 0) {
    658  1.1     alc 			*resultsize = sizeof(uint32_t);
    659  1.1     alc 			*((uint32_t *)(*result)) =
    660  1.1     alc 				AH_PRIVATE(ah)->ah_11nCompat;
    661  1.1     alc 		} else if (argsize == sizeof(uint32_t)) {
    662  1.1     alc 			AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
    663  1.1     alc 		} else
    664  1.1     alc 			return AH_FALSE;
    665  1.1     alc 		return AH_TRUE;
    666  1.1     alc 	}
    667  1.1     alc 	return AH_FALSE;
    668  1.1     alc }
    669  1.1     alc 
    670  1.1     alc /*
    671  1.1     alc  * Set the properties of the tx queue with the parameters
    672  1.1     alc  * from qInfo.
    673  1.1     alc  */
    674  1.1     alc HAL_BOOL
    675  1.1     alc ath_hal_setTxQProps(struct ath_hal *ah,
    676  1.1     alc 	HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
    677  1.1     alc {
    678  1.1     alc 	uint32_t cw;
    679  1.1     alc 
    680  1.1     alc 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
    681  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
    682  1.1     alc 		    "%s: inactive queue\n", __func__);
    683  1.1     alc 		return AH_FALSE;
    684  1.1     alc 	}
    685  1.1     alc 	/* XXX validate parameters */
    686  1.1     alc 	qi->tqi_ver = qInfo->tqi_ver;
    687  1.1     alc 	qi->tqi_subtype = qInfo->tqi_subtype;
    688  1.1     alc 	qi->tqi_qflags = qInfo->tqi_qflags;
    689  1.1     alc 	qi->tqi_priority = qInfo->tqi_priority;
    690  1.1     alc 	if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
    691  1.1     alc 		qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
    692  1.1     alc 	else
    693  1.1     alc 		qi->tqi_aifs = INIT_AIFS;
    694  1.1     alc 	if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
    695  1.1     alc 		cw = AH_MIN(qInfo->tqi_cwmin, 1024);
    696  1.1     alc 		/* make sure that the CWmin is of the form (2^n - 1) */
    697  1.1     alc 		qi->tqi_cwmin = 1;
    698  1.1     alc 		while (qi->tqi_cwmin < cw)
    699  1.1     alc 			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
    700  1.1     alc 	} else
    701  1.1     alc 		qi->tqi_cwmin = qInfo->tqi_cwmin;
    702  1.1     alc 	if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
    703  1.1     alc 		cw = AH_MIN(qInfo->tqi_cwmax, 1024);
    704  1.1     alc 		/* make sure that the CWmax is of the form (2^n - 1) */
    705  1.1     alc 		qi->tqi_cwmax = 1;
    706  1.1     alc 		while (qi->tqi_cwmax < cw)
    707  1.1     alc 			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
    708  1.1     alc 	} else
    709  1.1     alc 		qi->tqi_cwmax = INIT_CWMAX;
    710  1.1     alc 	/* Set retry limit values */
    711  1.1     alc 	if (qInfo->tqi_shretry != 0)
    712  1.1     alc 		qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
    713  1.1     alc 	else
    714  1.1     alc 		qi->tqi_shretry = INIT_SH_RETRY;
    715  1.1     alc 	if (qInfo->tqi_lgretry != 0)
    716  1.1     alc 		qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
    717  1.1     alc 	else
    718  1.1     alc 		qi->tqi_lgretry = INIT_LG_RETRY;
    719  1.1     alc 	qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
    720  1.1     alc 	qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
    721  1.1     alc 	qi->tqi_burstTime = qInfo->tqi_burstTime;
    722  1.1     alc 	qi->tqi_readyTime = qInfo->tqi_readyTime;
    723  1.1     alc 
    724  1.1     alc 	switch (qInfo->tqi_subtype) {
    725  1.1     alc 	case HAL_WME_UPSD:
    726  1.1     alc 		if (qi->tqi_type == HAL_TX_QUEUE_DATA)
    727  1.1     alc 			qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
    728  1.1     alc 		break;
    729  1.1     alc 	default:
    730  1.1     alc 		break;		/* NB: silence compiler */
    731  1.1     alc 	}
    732  1.1     alc 	return AH_TRUE;
    733  1.1     alc }
    734  1.1     alc 
    735  1.1     alc HAL_BOOL
    736  1.1     alc ath_hal_getTxQProps(struct ath_hal *ah,
    737  1.1     alc 	HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
    738  1.1     alc {
    739  1.1     alc 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
    740  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
    741  1.1     alc 		    "%s: inactive queue\n", __func__);
    742  1.1     alc 		return AH_FALSE;
    743  1.1     alc 	}
    744  1.1     alc 
    745  1.1     alc 	qInfo->tqi_qflags = qi->tqi_qflags;
    746  1.1     alc 	qInfo->tqi_ver = qi->tqi_ver;
    747  1.1     alc 	qInfo->tqi_subtype = qi->tqi_subtype;
    748  1.1     alc 	qInfo->tqi_qflags = qi->tqi_qflags;
    749  1.1     alc 	qInfo->tqi_priority = qi->tqi_priority;
    750  1.1     alc 	qInfo->tqi_aifs = qi->tqi_aifs;
    751  1.1     alc 	qInfo->tqi_cwmin = qi->tqi_cwmin;
    752  1.1     alc 	qInfo->tqi_cwmax = qi->tqi_cwmax;
    753  1.1     alc 	qInfo->tqi_shretry = qi->tqi_shretry;
    754  1.1     alc 	qInfo->tqi_lgretry = qi->tqi_lgretry;
    755  1.1     alc 	qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
    756  1.1     alc 	qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
    757  1.1     alc 	qInfo->tqi_burstTime = qi->tqi_burstTime;
    758  1.1     alc 	qInfo->tqi_readyTime = qi->tqi_readyTime;
    759  1.1     alc 	return AH_TRUE;
    760  1.1     alc }
    761  1.1     alc 
    762  1.1     alc                                      /* 11a Turbo  11b  11g  108g */
    763  1.1     alc static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
    764  1.1     alc 
    765  1.1     alc /*
    766  1.1     alc  * Read the current channel noise floor and return.
    767  1.1     alc  * If nf cal hasn't finished, channel noise floor should be 0
    768  1.1     alc  * and we return a nominal value based on band and frequency.
    769  1.1     alc  *
    770  1.1     alc  * NB: This is a private routine used by per-chip code to
    771  1.1     alc  *     implement the ah_getChanNoise method.
    772  1.1     alc  */
    773  1.1     alc int16_t
    774  1.1     alc ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan)
    775  1.1     alc {
    776  1.1     alc 	HAL_CHANNEL_INTERNAL *ichan;
    777  1.1     alc 
    778  1.1     alc 	ichan = ath_hal_checkchannel(ah, chan);
    779  1.1     alc 	if (ichan == AH_NULL) {
    780  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_NFCAL,
    781  1.1     alc 		    "%s: invalid channel %u/0x%x; no mapping\n",
    782  1.1     alc 		    __func__, chan->channel, chan->channelFlags);
    783  1.1     alc 		return 0;
    784  1.1     alc 	}
    785  1.1     alc 	if (ichan->rawNoiseFloor == 0) {
    786  1.1     alc 		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
    787  1.1     alc 
    788  1.1     alc 		HALASSERT(mode < WIRELESS_MODE_MAX);
    789  1.1     alc 		return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
    790  1.1     alc 	} else
    791  1.1     alc 		return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
    792  1.1     alc }
    793  1.1     alc 
    794  1.1     alc /*
    795  1.1     alc  * Process all valid raw noise floors into the dBm noise floor values.
    796  1.1     alc  * Though our device has no reference for a dBm noise floor, we perform
    797  1.1     alc  * a relative minimization of NF's based on the lowest NF found across a
    798  1.1     alc  * channel scan.
    799  1.1     alc  */
    800  1.1     alc void
    801  1.1     alc ath_hal_process_noisefloor(struct ath_hal *ah)
    802  1.1     alc {
    803  1.1     alc 	HAL_CHANNEL_INTERNAL *c;
    804  1.1     alc 	int16_t correct2, correct5;
    805  1.1     alc 	int16_t lowest2, lowest5;
    806  1.1     alc 	int i;
    807  1.1     alc 
    808  1.1     alc 	/*
    809  1.1     alc 	 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
    810  1.1     alc 	 * for statistically recorded NF/channel deviation.
    811  1.1     alc 	 */
    812  1.1     alc 	correct2 = lowest2 = 0;
    813  1.1     alc 	correct5 = lowest5 = 0;
    814  1.1     alc 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
    815  1.1     alc 		WIRELESS_MODE mode;
    816  1.1     alc 		int16_t nf;
    817  1.1     alc 
    818  1.1     alc 		c = &AH_PRIVATE(ah)->ah_channels[i];
    819  1.1     alc 		if (c->rawNoiseFloor >= 0)
    820  1.1     alc 			continue;
    821  1.1     alc 		mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) c);
    822  1.1     alc 		HALASSERT(mode < WIRELESS_MODE_MAX);
    823  1.1     alc 		nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
    824  1.1     alc 			ath_hal_getNfAdjust(ah, c);
    825  1.1     alc 		if (IS_CHAN_5GHZ(c)) {
    826  1.1     alc 			if (nf < lowest5) {
    827  1.1     alc 				lowest5 = nf;
    828  1.1     alc 				correct5 = NOISE_FLOOR[mode] -
    829  1.1     alc 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
    830  1.1     alc 			}
    831  1.1     alc 		} else {
    832  1.1     alc 			if (nf < lowest2) {
    833  1.1     alc 				lowest2 = nf;
    834  1.1     alc 				correct2 = NOISE_FLOOR[mode] -
    835  1.1     alc 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
    836  1.1     alc 			}
    837  1.1     alc 		}
    838  1.1     alc 	}
    839  1.1     alc 
    840  1.1     alc 	/* Correct the channels to reach the expected NF value */
    841  1.1     alc 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
    842  1.1     alc 		c = &AH_PRIVATE(ah)->ah_channels[i];
    843  1.1     alc 		if (c->rawNoiseFloor >= 0)
    844  1.1     alc 			continue;
    845  1.1     alc 		/* Apply correction factor */
    846  1.1     alc 		c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
    847  1.1     alc 			(IS_CHAN_5GHZ(c) ? correct5 : correct2);
    848  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u/0x%x raw nf %d adjust %d\n",
    849  1.1     alc 		    c->channel, c->channelFlags, c->rawNoiseFloor,
    850  1.1     alc 		    c->noiseFloorAdjust);
    851  1.1     alc 	}
    852  1.1     alc }
    853  1.1     alc 
    854  1.1     alc /*
    855  1.1     alc  * INI support routines.
    856  1.1     alc  */
    857  1.1     alc 
    858  1.1     alc int
    859  1.1     alc ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
    860  1.1     alc 	int col, int regWr)
    861  1.1     alc {
    862  1.1     alc 	int r;
    863  1.1     alc 
    864  1.1     alc 	for (r = 0; r < ia->rows; r++) {
    865  1.1     alc 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
    866  1.1     alc 		    HAL_INI_VAL(ia, r, col));
    867  1.1     alc 		DMA_YIELD(regWr);
    868  1.1     alc 	}
    869  1.1     alc 	return regWr;
    870  1.1     alc }
    871  1.1     alc 
    872  1.1     alc void
    873  1.1     alc ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
    874  1.1     alc {
    875  1.1     alc 	int r;
    876  1.1     alc 
    877  1.1     alc 	for (r = 0; r < ia->rows; r++)
    878  1.1     alc 		data[r] = HAL_INI_VAL(ia, r, col);
    879  1.1     alc }
    880  1.1     alc 
    881  1.1     alc int
    882  1.1     alc ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
    883  1.1     alc 	const uint32_t data[], int regWr)
    884  1.1     alc {
    885  1.1     alc 	int r;
    886  1.1     alc 
    887  1.1     alc 	for (r = 0; r < ia->rows; r++) {
    888  1.1     alc 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
    889  1.1     alc 		DMA_YIELD(regWr);
    890  1.1     alc 	}
    891  1.1     alc 	return regWr;
    892  1.1     alc }
    893