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