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