xref: /freebsd/sys/dev/ath/ath_hal/ah.c (revision 39beb93c)
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 		/* we still save OFDM rates in kbps - so double them */
291 		bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
292 		HALASSERT(bitsPerSymbol != 0);
293 
294 		numBits		= TURBO_PLCP_BITS + (frameLen << 3);
295 		numSymbols	= howmany(numBits, bitsPerSymbol);
296 		txTime		= TURBO_SIFS_TIME
297 				+ TURBO_PREAMBLE_TIME
298 				+ (numSymbols * TURBO_SYMBOL_TIME);
299 		break;
300 	default:
301 		HALDEBUG(ah, HAL_DEBUG_PHYIO,
302 		    "%s: unknown phy %u (rate ix %u)\n",
303 		    __func__, rates->info[rateix].phy, rateix);
304 		txTime = 0;
305 		break;
306 	}
307 	return txTime;
308 }
309 
310 typedef enum {
311 	WIRELESS_MODE_11a   = 0,
312 	WIRELESS_MODE_TURBO = 1,
313 	WIRELESS_MODE_11b   = 2,
314 	WIRELESS_MODE_11g   = 3,
315 	WIRELESS_MODE_108g  = 4,
316 
317 	WIRELESS_MODE_MAX
318 } WIRELESS_MODE;
319 
320 static WIRELESS_MODE
321 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
322 {
323 	if (IEEE80211_IS_CHAN_B(chan))
324 		return WIRELESS_MODE_11b;
325 	if (IEEE80211_IS_CHAN_G(chan))
326 		return WIRELESS_MODE_11g;
327 	if (IEEE80211_IS_CHAN_108G(chan))
328 		return WIRELESS_MODE_108g;
329 	if (IEEE80211_IS_CHAN_TURBO(chan))
330 		return WIRELESS_MODE_TURBO;
331 	return WIRELESS_MODE_11a;
332 }
333 
334 /*
335  * Convert between microseconds and core system clocks.
336  */
337                                      /* 11a Turbo  11b  11g  108g */
338 static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
339 
340 u_int
341 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
342 {
343 	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
344 	u_int clks;
345 
346 	/* NB: ah_curchan may be null when called attach time */
347 	if (c != AH_NULL) {
348 		clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
349 		if (IEEE80211_IS_CHAN_HT40(c))
350 			clks <<= 1;
351 	} else
352 		clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
353 	return clks;
354 }
355 
356 u_int
357 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
358 {
359 	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
360 	u_int usec;
361 
362 	/* NB: ah_curchan may be null when called attach time */
363 	if (c != AH_NULL) {
364 		usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
365 		if (IEEE80211_IS_CHAN_HT40(c))
366 			usec >>= 1;
367 	} else
368 		usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
369 	return usec;
370 }
371 
372 /*
373  * Setup a h/w rate table's reverse lookup table and
374  * fill in ack durations.  This routine is called for
375  * each rate table returned through the ah_getRateTable
376  * method.  The reverse lookup tables are assumed to be
377  * initialized to zero (or at least the first entry).
378  * We use this as a key that indicates whether or not
379  * we've previously setup the reverse lookup table.
380  *
381  * XXX not reentrant, but shouldn't matter
382  */
383 void
384 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
385 {
386 #define	N(a)	(sizeof(a)/sizeof(a[0]))
387 	int i;
388 
389 	if (rt->rateCodeToIndex[0] != 0)	/* already setup */
390 		return;
391 	for (i = 0; i < N(rt->rateCodeToIndex); i++)
392 		rt->rateCodeToIndex[i] = (uint8_t) -1;
393 	for (i = 0; i < rt->rateCount; i++) {
394 		uint8_t code = rt->info[i].rateCode;
395 		uint8_t cix = rt->info[i].controlRate;
396 
397 		HALASSERT(code < N(rt->rateCodeToIndex));
398 		rt->rateCodeToIndex[code] = i;
399 		HALASSERT((code | rt->info[i].shortPreamble) <
400 		    N(rt->rateCodeToIndex));
401 		rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
402 		/*
403 		 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
404 		 *     depends on whether they are marked as basic rates;
405 		 *     the static tables are setup with an 11b-compatible
406 		 *     2Mb/s rate which will work but is suboptimal
407 		 */
408 		rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
409 			WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
410 		rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
411 			WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
412 	}
413 #undef N
414 }
415 
416 HAL_STATUS
417 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
418 	uint32_t capability, uint32_t *result)
419 {
420 	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
421 
422 	switch (type) {
423 	case HAL_CAP_REG_DMN:		/* regulatory domain */
424 		*result = AH_PRIVATE(ah)->ah_currentRD;
425 		return HAL_OK;
426 	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
427 	case HAL_CAP_TKIP_MIC:		/* handle TKIP MIC in hardware */
428 		return HAL_ENOTSUPP;
429 	case HAL_CAP_TKIP_SPLIT:	/* hardware TKIP uses split keys */
430 		return HAL_ENOTSUPP;
431 	case HAL_CAP_PHYCOUNTERS:	/* hardware PHY error counters */
432 		return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
433 	case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
434 		return HAL_ENOTSUPP;
435 	case HAL_CAP_DIVERSITY:		/* hardware supports fast diversity */
436 		return HAL_ENOTSUPP;
437 	case HAL_CAP_KEYCACHE_SIZE:	/* hardware key cache size */
438 		*result =  pCap->halKeyCacheSize;
439 		return HAL_OK;
440 	case HAL_CAP_NUM_TXQUEUES:	/* number of hardware tx queues */
441 		*result = pCap->halTotalQueues;
442 		return HAL_OK;
443 	case HAL_CAP_VEOL:		/* hardware supports virtual EOL */
444 		return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
445 	case HAL_CAP_PSPOLL:		/* hardware PS-Poll support works */
446 		return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
447 	case HAL_CAP_COMPRESSION:
448 		return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
449 	case HAL_CAP_BURST:
450 		return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
451 	case HAL_CAP_FASTFRAME:
452 		return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
453 	case HAL_CAP_DIAG:		/* hardware diagnostic support */
454 		*result = AH_PRIVATE(ah)->ah_diagreg;
455 		return HAL_OK;
456 	case HAL_CAP_TXPOW:		/* global tx power limit  */
457 		switch (capability) {
458 		case 0:			/* facility is supported */
459 			return HAL_OK;
460 		case 1:			/* current limit */
461 			*result = AH_PRIVATE(ah)->ah_powerLimit;
462 			return HAL_OK;
463 		case 2:			/* current max tx power */
464 			*result = AH_PRIVATE(ah)->ah_maxPowerLevel;
465 			return HAL_OK;
466 		case 3:			/* scale factor */
467 			*result = AH_PRIVATE(ah)->ah_tpScale;
468 			return HAL_OK;
469 		}
470 		return HAL_ENOTSUPP;
471 	case HAL_CAP_BSSIDMASK:		/* hardware supports bssid mask */
472 		return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
473 	case HAL_CAP_MCAST_KEYSRCH:	/* multicast frame keycache search */
474 		return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
475 	case HAL_CAP_TSF_ADJUST:	/* hardware has beacon tsf adjust */
476 		return HAL_ENOTSUPP;
477 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
478 		switch (capability) {
479 		case 0:			/* facility is supported */
480 			return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
481 		case 1:			/* current setting */
482 			return AH_PRIVATE(ah)->ah_rfkillEnabled ?
483 				HAL_OK : HAL_ENOTSUPP;
484 		case 2:			/* rfsilent config */
485 			*result = AH_PRIVATE(ah)->ah_rfsilent;
486 			return HAL_OK;
487 		}
488 		return HAL_ENOTSUPP;
489 	case HAL_CAP_11D:
490 		return HAL_OK;
491 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
492 		return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
493 	case HAL_CAP_HT:
494 		return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
495 	case HAL_CAP_TX_CHAINMASK:	/* mask of TX chains supported */
496 		*result = pCap->halTxChainMask;
497 		return HAL_OK;
498 	case HAL_CAP_RX_CHAINMASK:	/* mask of RX chains supported */
499 		*result = pCap->halRxChainMask;
500 		return HAL_OK;
501 	case HAL_CAP_RXTSTAMP_PREC:	/* rx desc tstamp precision (bits) */
502 		*result = pCap->halTstampPrecision;
503 		return HAL_OK;
504 	default:
505 		return HAL_EINVAL;
506 	}
507 }
508 
509 HAL_BOOL
510 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
511 	uint32_t capability, uint32_t setting, HAL_STATUS *status)
512 {
513 
514 	switch (type) {
515 	case HAL_CAP_TXPOW:
516 		switch (capability) {
517 		case 3:
518 			if (setting <= HAL_TP_SCALE_MIN) {
519 				AH_PRIVATE(ah)->ah_tpScale = setting;
520 				return AH_TRUE;
521 			}
522 			break;
523 		}
524 		break;
525 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
526 		/*
527 		 * NB: allow even if halRfSilentSupport is false
528 		 *     in case the EEPROM is misprogrammed.
529 		 */
530 		switch (capability) {
531 		case 1:			/* current setting */
532 			AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
533 			return AH_TRUE;
534 		case 2:			/* rfsilent config */
535 			/* XXX better done per-chip for validation? */
536 			AH_PRIVATE(ah)->ah_rfsilent = setting;
537 			return AH_TRUE;
538 		}
539 		break;
540 	case HAL_CAP_REG_DMN:		/* regulatory domain */
541 		AH_PRIVATE(ah)->ah_currentRD = setting;
542 		return AH_TRUE;
543 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
544 		AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
545 		return AH_TRUE;
546 	default:
547 		break;
548 	}
549 	if (status)
550 		*status = HAL_EINVAL;
551 	return AH_FALSE;
552 }
553 
554 /*
555  * Common support for getDiagState method.
556  */
557 
558 static u_int
559 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
560 	void *dstbuf, int space)
561 {
562 	uint32_t *dp = dstbuf;
563 	int i;
564 
565 	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
566 		u_int r = regs[i].start;
567 		u_int e = regs[i].end;
568 		*dp++ = (r<<16) | e;
569 		space -= sizeof(uint32_t);
570 		do {
571 			*dp++ = OS_REG_READ(ah, r);
572 			r += sizeof(uint32_t);
573 			space -= sizeof(uint32_t);
574 		} while (r <= e && space >= sizeof(uint32_t));
575 	}
576 	return (char *) dp - (char *) dstbuf;
577 }
578 
579 static void
580 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
581 {
582 	while (space >= sizeof(HAL_REGWRITE)) {
583 		OS_REG_WRITE(ah, regs->addr, regs->value);
584 		regs++, space -= sizeof(HAL_REGWRITE);
585 	}
586 }
587 
588 HAL_BOOL
589 ath_hal_getdiagstate(struct ath_hal *ah, int request,
590 	const void *args, uint32_t argsize,
591 	void **result, uint32_t *resultsize)
592 {
593 	switch (request) {
594 	case HAL_DIAG_REVS:
595 		*result = &AH_PRIVATE(ah)->ah_devid;
596 		*resultsize = sizeof(HAL_REVS);
597 		return AH_TRUE;
598 	case HAL_DIAG_REGS:
599 		*resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
600 		return AH_TRUE;
601 	case HAL_DIAG_SETREGS:
602 		ath_hal_setregs(ah, args, argsize);
603 		*resultsize = 0;
604 		return AH_TRUE;
605 	case HAL_DIAG_FATALERR:
606 		*result = &AH_PRIVATE(ah)->ah_fatalState[0];
607 		*resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
608 		return AH_TRUE;
609 	case HAL_DIAG_EEREAD:
610 		if (argsize != sizeof(uint16_t))
611 			return AH_FALSE;
612 		if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
613 			return AH_FALSE;
614 		*resultsize = sizeof(uint16_t);
615 		return AH_TRUE;
616 #ifdef AH_PRIVATE_DIAG
617 	case HAL_DIAG_SETKEY: {
618 		const HAL_DIAG_KEYVAL *dk;
619 
620 		if (argsize != sizeof(HAL_DIAG_KEYVAL))
621 			return AH_FALSE;
622 		dk = (const HAL_DIAG_KEYVAL *)args;
623 		return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
624 			&dk->dk_keyval, dk->dk_mac, dk->dk_xor);
625 	}
626 	case HAL_DIAG_RESETKEY:
627 		if (argsize != sizeof(uint16_t))
628 			return AH_FALSE;
629 		return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
630 #ifdef AH_SUPPORT_WRITE_EEPROM
631 	case HAL_DIAG_EEWRITE: {
632 		const HAL_DIAG_EEVAL *ee;
633 		if (argsize != sizeof(HAL_DIAG_EEVAL))
634 			return AH_FALSE;
635 		ee = (const HAL_DIAG_EEVAL *)args;
636 		return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
637 	}
638 #endif /* AH_SUPPORT_WRITE_EEPROM */
639 #endif /* AH_PRIVATE_DIAG */
640 	case HAL_DIAG_11NCOMPAT:
641 		if (argsize == 0) {
642 			*resultsize = sizeof(uint32_t);
643 			*((uint32_t *)(*result)) =
644 				AH_PRIVATE(ah)->ah_11nCompat;
645 		} else if (argsize == sizeof(uint32_t)) {
646 			AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
647 		} else
648 			return AH_FALSE;
649 		return AH_TRUE;
650 	}
651 	return AH_FALSE;
652 }
653 
654 /*
655  * Set the properties of the tx queue with the parameters
656  * from qInfo.
657  */
658 HAL_BOOL
659 ath_hal_setTxQProps(struct ath_hal *ah,
660 	HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
661 {
662 	uint32_t cw;
663 
664 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
665 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
666 		    "%s: inactive queue\n", __func__);
667 		return AH_FALSE;
668 	}
669 	/* XXX validate parameters */
670 	qi->tqi_ver = qInfo->tqi_ver;
671 	qi->tqi_subtype = qInfo->tqi_subtype;
672 	qi->tqi_qflags = qInfo->tqi_qflags;
673 	qi->tqi_priority = qInfo->tqi_priority;
674 	if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
675 		qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
676 	else
677 		qi->tqi_aifs = INIT_AIFS;
678 	if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
679 		cw = AH_MIN(qInfo->tqi_cwmin, 1024);
680 		/* make sure that the CWmin is of the form (2^n - 1) */
681 		qi->tqi_cwmin = 1;
682 		while (qi->tqi_cwmin < cw)
683 			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
684 	} else
685 		qi->tqi_cwmin = qInfo->tqi_cwmin;
686 	if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
687 		cw = AH_MIN(qInfo->tqi_cwmax, 1024);
688 		/* make sure that the CWmax is of the form (2^n - 1) */
689 		qi->tqi_cwmax = 1;
690 		while (qi->tqi_cwmax < cw)
691 			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
692 	} else
693 		qi->tqi_cwmax = INIT_CWMAX;
694 	/* Set retry limit values */
695 	if (qInfo->tqi_shretry != 0)
696 		qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
697 	else
698 		qi->tqi_shretry = INIT_SH_RETRY;
699 	if (qInfo->tqi_lgretry != 0)
700 		qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
701 	else
702 		qi->tqi_lgretry = INIT_LG_RETRY;
703 	qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
704 	qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
705 	qi->tqi_burstTime = qInfo->tqi_burstTime;
706 	qi->tqi_readyTime = qInfo->tqi_readyTime;
707 
708 	switch (qInfo->tqi_subtype) {
709 	case HAL_WME_UPSD:
710 		if (qi->tqi_type == HAL_TX_QUEUE_DATA)
711 			qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
712 		break;
713 	default:
714 		break;		/* NB: silence compiler */
715 	}
716 	return AH_TRUE;
717 }
718 
719 HAL_BOOL
720 ath_hal_getTxQProps(struct ath_hal *ah,
721 	HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
722 {
723 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
724 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
725 		    "%s: inactive queue\n", __func__);
726 		return AH_FALSE;
727 	}
728 
729 	qInfo->tqi_qflags = qi->tqi_qflags;
730 	qInfo->tqi_ver = qi->tqi_ver;
731 	qInfo->tqi_subtype = qi->tqi_subtype;
732 	qInfo->tqi_qflags = qi->tqi_qflags;
733 	qInfo->tqi_priority = qi->tqi_priority;
734 	qInfo->tqi_aifs = qi->tqi_aifs;
735 	qInfo->tqi_cwmin = qi->tqi_cwmin;
736 	qInfo->tqi_cwmax = qi->tqi_cwmax;
737 	qInfo->tqi_shretry = qi->tqi_shretry;
738 	qInfo->tqi_lgretry = qi->tqi_lgretry;
739 	qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
740 	qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
741 	qInfo->tqi_burstTime = qi->tqi_burstTime;
742 	qInfo->tqi_readyTime = qi->tqi_readyTime;
743 	return AH_TRUE;
744 }
745 
746                                      /* 11a Turbo  11b  11g  108g */
747 static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
748 
749 /*
750  * Read the current channel noise floor and return.
751  * If nf cal hasn't finished, channel noise floor should be 0
752  * and we return a nominal value based on band and frequency.
753  *
754  * NB: This is a private routine used by per-chip code to
755  *     implement the ah_getChanNoise method.
756  */
757 int16_t
758 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
759 {
760 	HAL_CHANNEL_INTERNAL *ichan;
761 
762 	ichan = ath_hal_checkchannel(ah, chan);
763 	if (ichan == AH_NULL) {
764 		HALDEBUG(ah, HAL_DEBUG_NFCAL,
765 		    "%s: invalid channel %u/0x%x; no mapping\n",
766 		    __func__, chan->ic_freq, chan->ic_flags);
767 		return 0;
768 	}
769 	if (ichan->rawNoiseFloor == 0) {
770 		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
771 
772 		HALASSERT(mode < WIRELESS_MODE_MAX);
773 		return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
774 	} else
775 		return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
776 }
777 
778 /*
779  * Process all valid raw noise floors into the dBm noise floor values.
780  * Though our device has no reference for a dBm noise floor, we perform
781  * a relative minimization of NF's based on the lowest NF found across a
782  * channel scan.
783  */
784 void
785 ath_hal_process_noisefloor(struct ath_hal *ah)
786 {
787 	HAL_CHANNEL_INTERNAL *c;
788 	int16_t correct2, correct5;
789 	int16_t lowest2, lowest5;
790 	int i;
791 
792 	/*
793 	 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
794 	 * for statistically recorded NF/channel deviation.
795 	 */
796 	correct2 = lowest2 = 0;
797 	correct5 = lowest5 = 0;
798 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
799 		WIRELESS_MODE mode;
800 		int16_t nf;
801 
802 		c = &AH_PRIVATE(ah)->ah_channels[i];
803 		if (c->rawNoiseFloor >= 0)
804 			continue;
805 		/* XXX can't identify proper mode */
806 		mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
807 		nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
808 			ath_hal_getNfAdjust(ah, c);
809 		if (IS_CHAN_5GHZ(c)) {
810 			if (nf < lowest5) {
811 				lowest5 = nf;
812 				correct5 = NOISE_FLOOR[mode] -
813 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
814 			}
815 		} else {
816 			if (nf < lowest2) {
817 				lowest2 = nf;
818 				correct2 = NOISE_FLOOR[mode] -
819 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
820 			}
821 		}
822 	}
823 
824 	/* Correct the channels to reach the expected NF value */
825 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
826 		c = &AH_PRIVATE(ah)->ah_channels[i];
827 		if (c->rawNoiseFloor >= 0)
828 			continue;
829 		/* Apply correction factor */
830 		c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
831 			(IS_CHAN_5GHZ(c) ? correct5 : correct2);
832 		HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
833 		    c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
834 	}
835 }
836 
837 /*
838  * INI support routines.
839  */
840 
841 int
842 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
843 	int col, int regWr)
844 {
845 	int r;
846 
847 	for (r = 0; r < ia->rows; r++) {
848 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
849 		    HAL_INI_VAL(ia, r, col));
850 		DMA_YIELD(regWr);
851 	}
852 	return regWr;
853 }
854 
855 void
856 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
857 {
858 	int r;
859 
860 	for (r = 0; r < ia->rows; r++)
861 		data[r] = HAL_INI_VAL(ia, r, col);
862 }
863 
864 int
865 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
866 	const uint32_t data[], int regWr)
867 {
868 	int r;
869 
870 	for (r = 0; r < ia->rows; r++) {
871 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
872 		DMA_YIELD(regWr);
873 	}
874 	return regWr;
875 }
876