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