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