xref: /freebsd/sys/dev/ath/ath_hal/ah.c (revision 195ebc7e9e4b129de810833791a19dfb4349d6a9)
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 	default:
507 		return HAL_EINVAL;
508 	}
509 }
510 
511 HAL_BOOL
512 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
513 	uint32_t capability, uint32_t setting, HAL_STATUS *status)
514 {
515 
516 	switch (type) {
517 	case HAL_CAP_TXPOW:
518 		switch (capability) {
519 		case 3:
520 			if (setting <= HAL_TP_SCALE_MIN) {
521 				AH_PRIVATE(ah)->ah_tpScale = setting;
522 				return AH_TRUE;
523 			}
524 			break;
525 		}
526 		break;
527 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
528 		/*
529 		 * NB: allow even if halRfSilentSupport is false
530 		 *     in case the EEPROM is misprogrammed.
531 		 */
532 		switch (capability) {
533 		case 1:			/* current setting */
534 			AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
535 			return AH_TRUE;
536 		case 2:			/* rfsilent config */
537 			/* XXX better done per-chip for validation? */
538 			AH_PRIVATE(ah)->ah_rfsilent = setting;
539 			return AH_TRUE;
540 		}
541 		break;
542 	case HAL_CAP_REG_DMN:		/* regulatory domain */
543 		AH_PRIVATE(ah)->ah_currentRD = setting;
544 		return AH_TRUE;
545 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
546 		AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
547 		return AH_TRUE;
548 	default:
549 		break;
550 	}
551 	if (status)
552 		*status = HAL_EINVAL;
553 	return AH_FALSE;
554 }
555 
556 /*
557  * Common support for getDiagState method.
558  */
559 
560 static u_int
561 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
562 	void *dstbuf, int space)
563 {
564 	uint32_t *dp = dstbuf;
565 	int i;
566 
567 	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
568 		u_int r = regs[i].start;
569 		u_int e = regs[i].end;
570 		*dp++ = (r<<16) | e;
571 		space -= sizeof(uint32_t);
572 		do {
573 			*dp++ = OS_REG_READ(ah, r);
574 			r += sizeof(uint32_t);
575 			space -= sizeof(uint32_t);
576 		} while (r <= e && space >= sizeof(uint32_t));
577 	}
578 	return (char *) dp - (char *) dstbuf;
579 }
580 
581 static void
582 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
583 {
584 	while (space >= sizeof(HAL_REGWRITE)) {
585 		OS_REG_WRITE(ah, regs->addr, regs->value);
586 		regs++, space -= sizeof(HAL_REGWRITE);
587 	}
588 }
589 
590 HAL_BOOL
591 ath_hal_getdiagstate(struct ath_hal *ah, int request,
592 	const void *args, uint32_t argsize,
593 	void **result, uint32_t *resultsize)
594 {
595 	switch (request) {
596 	case HAL_DIAG_REVS:
597 		*result = &AH_PRIVATE(ah)->ah_devid;
598 		*resultsize = sizeof(HAL_REVS);
599 		return AH_TRUE;
600 	case HAL_DIAG_REGS:
601 		*resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
602 		return AH_TRUE;
603 	case HAL_DIAG_SETREGS:
604 		ath_hal_setregs(ah, args, argsize);
605 		*resultsize = 0;
606 		return AH_TRUE;
607 	case HAL_DIAG_FATALERR:
608 		*result = &AH_PRIVATE(ah)->ah_fatalState[0];
609 		*resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
610 		return AH_TRUE;
611 	case HAL_DIAG_EEREAD:
612 		if (argsize != sizeof(uint16_t))
613 			return AH_FALSE;
614 		if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
615 			return AH_FALSE;
616 		*resultsize = sizeof(uint16_t);
617 		return AH_TRUE;
618 #ifdef AH_PRIVATE_DIAG
619 	case HAL_DIAG_SETKEY: {
620 		const HAL_DIAG_KEYVAL *dk;
621 
622 		if (argsize != sizeof(HAL_DIAG_KEYVAL))
623 			return AH_FALSE;
624 		dk = (const HAL_DIAG_KEYVAL *)args;
625 		return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
626 			&dk->dk_keyval, dk->dk_mac, dk->dk_xor);
627 	}
628 	case HAL_DIAG_RESETKEY:
629 		if (argsize != sizeof(uint16_t))
630 			return AH_FALSE;
631 		return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
632 #ifdef AH_SUPPORT_WRITE_EEPROM
633 	case HAL_DIAG_EEWRITE: {
634 		const HAL_DIAG_EEVAL *ee;
635 		if (argsize != sizeof(HAL_DIAG_EEVAL))
636 			return AH_FALSE;
637 		ee = (const HAL_DIAG_EEVAL *)args;
638 		return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
639 	}
640 #endif /* AH_SUPPORT_WRITE_EEPROM */
641 #endif /* AH_PRIVATE_DIAG */
642 	case HAL_DIAG_11NCOMPAT:
643 		if (argsize == 0) {
644 			*resultsize = sizeof(uint32_t);
645 			*((uint32_t *)(*result)) =
646 				AH_PRIVATE(ah)->ah_11nCompat;
647 		} else if (argsize == sizeof(uint32_t)) {
648 			AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
649 		} else
650 			return AH_FALSE;
651 		return AH_TRUE;
652 	}
653 	return AH_FALSE;
654 }
655 
656 /*
657  * Set the properties of the tx queue with the parameters
658  * from qInfo.
659  */
660 HAL_BOOL
661 ath_hal_setTxQProps(struct ath_hal *ah,
662 	HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
663 {
664 	uint32_t cw;
665 
666 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
667 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
668 		    "%s: inactive queue\n", __func__);
669 		return AH_FALSE;
670 	}
671 	/* XXX validate parameters */
672 	qi->tqi_ver = qInfo->tqi_ver;
673 	qi->tqi_subtype = qInfo->tqi_subtype;
674 	qi->tqi_qflags = qInfo->tqi_qflags;
675 	qi->tqi_priority = qInfo->tqi_priority;
676 	if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
677 		qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
678 	else
679 		qi->tqi_aifs = INIT_AIFS;
680 	if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
681 		cw = AH_MIN(qInfo->tqi_cwmin, 1024);
682 		/* make sure that the CWmin is of the form (2^n - 1) */
683 		qi->tqi_cwmin = 1;
684 		while (qi->tqi_cwmin < cw)
685 			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
686 	} else
687 		qi->tqi_cwmin = qInfo->tqi_cwmin;
688 	if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
689 		cw = AH_MIN(qInfo->tqi_cwmax, 1024);
690 		/* make sure that the CWmax is of the form (2^n - 1) */
691 		qi->tqi_cwmax = 1;
692 		while (qi->tqi_cwmax < cw)
693 			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
694 	} else
695 		qi->tqi_cwmax = INIT_CWMAX;
696 	/* Set retry limit values */
697 	if (qInfo->tqi_shretry != 0)
698 		qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
699 	else
700 		qi->tqi_shretry = INIT_SH_RETRY;
701 	if (qInfo->tqi_lgretry != 0)
702 		qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
703 	else
704 		qi->tqi_lgretry = INIT_LG_RETRY;
705 	qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
706 	qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
707 	qi->tqi_burstTime = qInfo->tqi_burstTime;
708 	qi->tqi_readyTime = qInfo->tqi_readyTime;
709 
710 	switch (qInfo->tqi_subtype) {
711 	case HAL_WME_UPSD:
712 		if (qi->tqi_type == HAL_TX_QUEUE_DATA)
713 			qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
714 		break;
715 	default:
716 		break;		/* NB: silence compiler */
717 	}
718 	return AH_TRUE;
719 }
720 
721 HAL_BOOL
722 ath_hal_getTxQProps(struct ath_hal *ah,
723 	HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
724 {
725 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
726 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
727 		    "%s: inactive queue\n", __func__);
728 		return AH_FALSE;
729 	}
730 
731 	qInfo->tqi_qflags = qi->tqi_qflags;
732 	qInfo->tqi_ver = qi->tqi_ver;
733 	qInfo->tqi_subtype = qi->tqi_subtype;
734 	qInfo->tqi_qflags = qi->tqi_qflags;
735 	qInfo->tqi_priority = qi->tqi_priority;
736 	qInfo->tqi_aifs = qi->tqi_aifs;
737 	qInfo->tqi_cwmin = qi->tqi_cwmin;
738 	qInfo->tqi_cwmax = qi->tqi_cwmax;
739 	qInfo->tqi_shretry = qi->tqi_shretry;
740 	qInfo->tqi_lgretry = qi->tqi_lgretry;
741 	qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
742 	qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
743 	qInfo->tqi_burstTime = qi->tqi_burstTime;
744 	qInfo->tqi_readyTime = qi->tqi_readyTime;
745 	return AH_TRUE;
746 }
747 
748                                      /* 11a Turbo  11b  11g  108g */
749 static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
750 
751 /*
752  * Read the current channel noise floor and return.
753  * If nf cal hasn't finished, channel noise floor should be 0
754  * and we return a nominal value based on band and frequency.
755  *
756  * NB: This is a private routine used by per-chip code to
757  *     implement the ah_getChanNoise method.
758  */
759 int16_t
760 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
761 {
762 	HAL_CHANNEL_INTERNAL *ichan;
763 
764 	ichan = ath_hal_checkchannel(ah, chan);
765 	if (ichan == AH_NULL) {
766 		HALDEBUG(ah, HAL_DEBUG_NFCAL,
767 		    "%s: invalid channel %u/0x%x; no mapping\n",
768 		    __func__, chan->ic_freq, chan->ic_flags);
769 		return 0;
770 	}
771 	if (ichan->rawNoiseFloor == 0) {
772 		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
773 
774 		HALASSERT(mode < WIRELESS_MODE_MAX);
775 		return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
776 	} else
777 		return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
778 }
779 
780 /*
781  * Process all valid raw noise floors into the dBm noise floor values.
782  * Though our device has no reference for a dBm noise floor, we perform
783  * a relative minimization of NF's based on the lowest NF found across a
784  * channel scan.
785  */
786 void
787 ath_hal_process_noisefloor(struct ath_hal *ah)
788 {
789 	HAL_CHANNEL_INTERNAL *c;
790 	int16_t correct2, correct5;
791 	int16_t lowest2, lowest5;
792 	int i;
793 
794 	/*
795 	 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
796 	 * for statistically recorded NF/channel deviation.
797 	 */
798 	correct2 = lowest2 = 0;
799 	correct5 = lowest5 = 0;
800 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
801 		WIRELESS_MODE mode;
802 		int16_t nf;
803 
804 		c = &AH_PRIVATE(ah)->ah_channels[i];
805 		if (c->rawNoiseFloor >= 0)
806 			continue;
807 		/* XXX can't identify proper mode */
808 		mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
809 		nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
810 			ath_hal_getNfAdjust(ah, c);
811 		if (IS_CHAN_5GHZ(c)) {
812 			if (nf < lowest5) {
813 				lowest5 = nf;
814 				correct5 = NOISE_FLOOR[mode] -
815 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
816 			}
817 		} else {
818 			if (nf < lowest2) {
819 				lowest2 = nf;
820 				correct2 = NOISE_FLOOR[mode] -
821 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
822 			}
823 		}
824 	}
825 
826 	/* Correct the channels to reach the expected NF value */
827 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
828 		c = &AH_PRIVATE(ah)->ah_channels[i];
829 		if (c->rawNoiseFloor >= 0)
830 			continue;
831 		/* Apply correction factor */
832 		c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
833 			(IS_CHAN_5GHZ(c) ? correct5 : correct2);
834 		HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
835 		    c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
836 	}
837 }
838 
839 /*
840  * INI support routines.
841  */
842 
843 int
844 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
845 	int col, int regWr)
846 {
847 	int r;
848 
849 	HALASSERT(col < ia->cols);
850 	for (r = 0; r < ia->rows; r++) {
851 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
852 		    HAL_INI_VAL(ia, r, col));
853 		DMA_YIELD(regWr);
854 	}
855 	return regWr;
856 }
857 
858 void
859 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
860 {
861 	int r;
862 
863 	HALASSERT(col < ia->cols);
864 	for (r = 0; r < ia->rows; r++)
865 		data[r] = HAL_INI_VAL(ia, r, col);
866 }
867 
868 int
869 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
870 	const uint32_t data[], int regWr)
871 {
872 	int r;
873 
874 	for (r = 0; r < ia->rows; r++) {
875 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
876 		DMA_YIELD(regWr);
877 	}
878 	return regWr;
879 }
880