xref: /freebsd/sys/dev/ath/ath_hal/ah.c (revision f02f7422801bb39f5eaab8fc383fa7b70c467ff9)
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 #include "ah_eeprom.h"			/* for 5ghz fast clock flag */
25 
26 #include "ar5416/ar5416reg.h"		/* NB: includes ar5212reg.h */
27 #include "ar9003/ar9300_devid.h"
28 
29 /* linker set of registered chips */
30 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
31 
32 /*
33  * Check the set of registered chips to see if any recognize
34  * the device as one they can support.
35  */
36 const char*
37 ath_hal_probe(uint16_t vendorid, uint16_t devid)
38 {
39 	struct ath_hal_chip * const *pchip;
40 
41 	OS_SET_FOREACH(pchip, ah_chips) {
42 		const char *name = (*pchip)->probe(vendorid, devid);
43 		if (name != AH_NULL)
44 			return name;
45 	}
46 	return AH_NULL;
47 }
48 
49 /*
50  * Attach detects device chip revisions, initializes the hwLayer
51  * function list, reads EEPROM information,
52  * selects reset vectors, and performs a short self test.
53  * Any failures will return an error that should cause a hardware
54  * disable.
55  */
56 struct ath_hal*
57 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
58 	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *error)
59 {
60 	struct ath_hal_chip * const *pchip;
61 
62 	OS_SET_FOREACH(pchip, ah_chips) {
63 		struct ath_hal_chip *chip = *pchip;
64 		struct ath_hal *ah;
65 
66 		/* XXX don't have vendorid, assume atheros one works */
67 		if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
68 			continue;
69 		ah = chip->attach(devid, sc, st, sh, eepromdata, error);
70 		if (ah != AH_NULL) {
71 			/* copy back private state to public area */
72 			ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
73 			ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
74 			ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
75 			ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
76 			ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
77 			ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
78 			ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
79 			return ah;
80 		}
81 	}
82 	return AH_NULL;
83 }
84 
85 const char *
86 ath_hal_mac_name(struct ath_hal *ah)
87 {
88 	switch (ah->ah_macVersion) {
89 	case AR_SREV_VERSION_CRETE:
90 	case AR_SREV_VERSION_MAUI_1:
91 		return "5210";
92 	case AR_SREV_VERSION_MAUI_2:
93 	case AR_SREV_VERSION_OAHU:
94 		return "5211";
95 	case AR_SREV_VERSION_VENICE:
96 		return "5212";
97 	case AR_SREV_VERSION_GRIFFIN:
98 		return "2413";
99 	case AR_SREV_VERSION_CONDOR:
100 		return "5424";
101 	case AR_SREV_VERSION_EAGLE:
102 		return "5413";
103 	case AR_SREV_VERSION_COBRA:
104 		return "2415";
105 	case AR_SREV_2425:	/* Swan */
106 		return "2425";
107 	case AR_SREV_2417:	/* Nala */
108 		return "2417";
109 	case AR_XSREV_VERSION_OWL_PCI:
110 		return "5416";
111 	case AR_XSREV_VERSION_OWL_PCIE:
112 		return "5418";
113 	case AR_XSREV_VERSION_HOWL:
114 		return "9130";
115 	case AR_XSREV_VERSION_SOWL:
116 		return "9160";
117 	case AR_XSREV_VERSION_MERLIN:
118 		if (AH_PRIVATE(ah)->ah_ispcie)
119 			return "9280";
120 		return "9220";
121 	case AR_XSREV_VERSION_KITE:
122 		return "9285";
123 	case AR_XSREV_VERSION_KIWI:
124 		if (AH_PRIVATE(ah)->ah_ispcie)
125 			return "9287";
126 		return "9227";
127 	case AR_SREV_VERSION_AR9380:
128 		if (ah->ah_macRev >= AR_SREV_REVISION_AR9580_10)
129 			return "9580";
130 		return "9380";
131 	case AR_SREV_VERSION_AR9460:
132 		return "9460";
133 	case AR_SREV_VERSION_AR9330:
134 		return "9330";
135 	case AR_SREV_VERSION_AR9340:
136 		return "9340";
137 	case AR_SREV_VERSION_QCA9550:
138 		/* XXX should say QCA, not AR */
139 		return "9550";
140 	case AR_SREV_VERSION_AR9485:
141 		return "9485";
142 	case AR_SREV_VERSION_QCA9565:
143 		/* XXX should say QCA, not AR */
144 		return "9565";
145 	}
146 	return "????";
147 }
148 
149 /*
150  * Return the mask of available modes based on the hardware capabilities.
151  */
152 u_int
153 ath_hal_getwirelessmodes(struct ath_hal*ah)
154 {
155 	return ath_hal_getWirelessModes(ah);
156 }
157 
158 /* linker set of registered RF backends */
159 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
160 
161 /*
162  * Check the set of registered RF backends to see if
163  * any recognize the device as one they can support.
164  */
165 struct ath_hal_rf *
166 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
167 {
168 	struct ath_hal_rf * const *prf;
169 
170 	OS_SET_FOREACH(prf, ah_rfs) {
171 		struct ath_hal_rf *rf = *prf;
172 		if (rf->probe(ah))
173 			return rf;
174 	}
175 	*ecode = HAL_ENOTSUPP;
176 	return AH_NULL;
177 }
178 
179 const char *
180 ath_hal_rf_name(struct ath_hal *ah)
181 {
182 	switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
183 	case 0:			/* 5210 */
184 		return "5110";	/* NB: made up */
185 	case AR_RAD5111_SREV_MAJOR:
186 	case AR_RAD5111_SREV_PROD:
187 		return "5111";
188 	case AR_RAD2111_SREV_MAJOR:
189 		return "2111";
190 	case AR_RAD5112_SREV_MAJOR:
191 	case AR_RAD5112_SREV_2_0:
192 	case AR_RAD5112_SREV_2_1:
193 		return "5112";
194 	case AR_RAD2112_SREV_MAJOR:
195 	case AR_RAD2112_SREV_2_0:
196 	case AR_RAD2112_SREV_2_1:
197 		return "2112";
198 	case AR_RAD2413_SREV_MAJOR:
199 		return "2413";
200 	case AR_RAD5413_SREV_MAJOR:
201 		return "5413";
202 	case AR_RAD2316_SREV_MAJOR:
203 		return "2316";
204 	case AR_RAD2317_SREV_MAJOR:
205 		return "2317";
206 	case AR_RAD5424_SREV_MAJOR:
207 		return "5424";
208 
209 	case AR_RAD5133_SREV_MAJOR:
210 		return "5133";
211 	case AR_RAD2133_SREV_MAJOR:
212 		return "2133";
213 	case AR_RAD5122_SREV_MAJOR:
214 		return "5122";
215 	case AR_RAD2122_SREV_MAJOR:
216 		return "2122";
217 	}
218 	return "????";
219 }
220 
221 /*
222  * Poll the register looking for a specific value.
223  */
224 HAL_BOOL
225 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
226 {
227 #define	AH_TIMEOUT	1000
228 	return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
229 #undef AH_TIMEOUT
230 }
231 
232 HAL_BOOL
233 ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
234 {
235 	int i;
236 
237 	for (i = 0; i < timeout; i++) {
238 		if ((OS_REG_READ(ah, reg) & mask) == val)
239 			return AH_TRUE;
240 		OS_DELAY(10);
241 	}
242 	HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
243 	    "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
244 	    __func__, reg, OS_REG_READ(ah, reg), mask, val);
245 	return AH_FALSE;
246 }
247 
248 /*
249  * Reverse the bits starting at the low bit for a value of
250  * bit_count in size
251  */
252 uint32_t
253 ath_hal_reverseBits(uint32_t val, uint32_t n)
254 {
255 	uint32_t retval;
256 	int i;
257 
258 	for (i = 0, retval = 0; i < n; i++) {
259 		retval = (retval << 1) | (val & 1);
260 		val >>= 1;
261 	}
262 	return retval;
263 }
264 
265 /* 802.11n related timing definitions */
266 
267 #define	OFDM_PLCP_BITS	22
268 #define	HT_L_STF	8
269 #define	HT_L_LTF	8
270 #define	HT_L_SIG	4
271 #define	HT_SIG		8
272 #define	HT_STF		4
273 #define	HT_LTF(n)	((n) * 4)
274 
275 #define	HT_RC_2_MCS(_rc)	((_rc) & 0xf)
276 #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
277 #define	IS_HT_RATE(_rc)		( (_rc) & IEEE80211_RATE_MCS)
278 
279 /*
280  * Calculate the duration of a packet whether it is 11n or legacy.
281  */
282 uint32_t
283 ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
284     uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
285 {
286 	uint8_t rc;
287 	int numStreams;
288 
289 	rc = rates->info[rateix].rateCode;
290 
291 	/* Legacy rate? Return the old way */
292 	if (! IS_HT_RATE(rc))
293 		return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
294 
295 	/* 11n frame - extract out the number of spatial streams */
296 	numStreams = HT_RC_2_STREAMS(rc);
297 	KASSERT(numStreams > 0 && numStreams <= 4,
298 	    ("number of spatial streams needs to be 1..3: MCS rate 0x%x!",
299 	    rateix));
300 
301 	return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
302 }
303 
304 static const uint16_t ht20_bps[32] = {
305     26, 52, 78, 104, 156, 208, 234, 260,
306     52, 104, 156, 208, 312, 416, 468, 520,
307     78, 156, 234, 312, 468, 624, 702, 780,
308     104, 208, 312, 416, 624, 832, 936, 1040
309 };
310 static const uint16_t ht40_bps[32] = {
311     54, 108, 162, 216, 324, 432, 486, 540,
312     108, 216, 324, 432, 648, 864, 972, 1080,
313     162, 324, 486, 648, 972, 1296, 1458, 1620,
314     216, 432, 648, 864, 1296, 1728, 1944, 2160
315 };
316 
317 /*
318  * Calculate the transmit duration of an 11n frame.
319  */
320 uint32_t
321 ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams,
322     HAL_BOOL isht40, HAL_BOOL isShortGI)
323 {
324 	uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
325 
326 	KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
327 	KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate));
328 
329 	if (isht40)
330 		bitsPerSymbol = ht40_bps[rate & 0x1f];
331 	else
332 		bitsPerSymbol = ht20_bps[rate & 0x1f];
333 	numBits = OFDM_PLCP_BITS + (frameLen << 3);
334 	numSymbols = howmany(numBits, bitsPerSymbol);
335 	if (isShortGI)
336 		txTime = ((numSymbols * 18) + 4) / 5;   /* 3.6us */
337 	else
338 		txTime = numSymbols * 4;                /* 4us */
339 	return txTime + HT_L_STF + HT_L_LTF +
340 	    HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
341 }
342 
343 /*
344  * Compute the time to transmit a frame of length frameLen bytes
345  * using the specified rate, phy, and short preamble setting.
346  */
347 uint16_t
348 ath_hal_computetxtime(struct ath_hal *ah,
349 	const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
350 	HAL_BOOL shortPreamble)
351 {
352 	uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
353 	uint32_t kbps;
354 
355 	/* Warn if this function is called for 11n rates; it should not be! */
356 	if (IS_HT_RATE(rates->info[rateix].rateCode))
357 		ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
358 		    __func__, rateix, rates->info[rateix].rateCode);
359 
360 	kbps = rates->info[rateix].rateKbps;
361 	/*
362 	 * index can be invalid duting dynamic Turbo transitions.
363 	 * XXX
364 	 */
365 	if (kbps == 0)
366 		return 0;
367 	switch (rates->info[rateix].phy) {
368 	case IEEE80211_T_CCK:
369 		phyTime		= CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
370 		if (shortPreamble && rates->info[rateix].shortPreamble)
371 			phyTime >>= 1;
372 		numBits		= frameLen << 3;
373 		txTime		= CCK_SIFS_TIME + phyTime
374 				+ ((numBits * 1000)/kbps);
375 		break;
376 	case IEEE80211_T_OFDM:
377 		bitsPerSymbol	= (kbps * OFDM_SYMBOL_TIME) / 1000;
378 		HALASSERT(bitsPerSymbol != 0);
379 
380 		numBits		= OFDM_PLCP_BITS + (frameLen << 3);
381 		numSymbols	= howmany(numBits, bitsPerSymbol);
382 		txTime		= OFDM_SIFS_TIME
383 				+ OFDM_PREAMBLE_TIME
384 				+ (numSymbols * OFDM_SYMBOL_TIME);
385 		break;
386 	case IEEE80211_T_OFDM_HALF:
387 		bitsPerSymbol	= (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
388 		HALASSERT(bitsPerSymbol != 0);
389 
390 		numBits		= OFDM_HALF_PLCP_BITS + (frameLen << 3);
391 		numSymbols	= howmany(numBits, bitsPerSymbol);
392 		txTime		= OFDM_HALF_SIFS_TIME
393 				+ OFDM_HALF_PREAMBLE_TIME
394 				+ (numSymbols * OFDM_HALF_SYMBOL_TIME);
395 		break;
396 	case IEEE80211_T_OFDM_QUARTER:
397 		bitsPerSymbol	= (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
398 		HALASSERT(bitsPerSymbol != 0);
399 
400 		numBits		= OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
401 		numSymbols	= howmany(numBits, bitsPerSymbol);
402 		txTime		= OFDM_QUARTER_SIFS_TIME
403 				+ OFDM_QUARTER_PREAMBLE_TIME
404 				+ (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
405 		break;
406 	case IEEE80211_T_TURBO:
407 		bitsPerSymbol	= (kbps * TURBO_SYMBOL_TIME) / 1000;
408 		HALASSERT(bitsPerSymbol != 0);
409 
410 		numBits		= TURBO_PLCP_BITS + (frameLen << 3);
411 		numSymbols	= howmany(numBits, bitsPerSymbol);
412 		txTime		= TURBO_SIFS_TIME
413 				+ TURBO_PREAMBLE_TIME
414 				+ (numSymbols * TURBO_SYMBOL_TIME);
415 		break;
416 	default:
417 		HALDEBUG(ah, HAL_DEBUG_PHYIO,
418 		    "%s: unknown phy %u (rate ix %u)\n",
419 		    __func__, rates->info[rateix].phy, rateix);
420 		txTime = 0;
421 		break;
422 	}
423 	return txTime;
424 }
425 
426 int
427 ath_hal_get_curmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
428 {
429 	/*
430 	 * Pick a default mode at bootup. A channel change is inevitable.
431 	 */
432 	if (!chan)
433 		return HAL_MODE_11NG_HT20;
434 
435 	if (IEEE80211_IS_CHAN_TURBO(chan))
436 		return HAL_MODE_TURBO;
437 
438 	/* check for NA_HT before plain A, since IS_CHAN_A includes NA_HT */
439 	if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
440 		return HAL_MODE_11NA_HT20;
441 	if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
442 		return HAL_MODE_11NA_HT40PLUS;
443 	if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
444 		return HAL_MODE_11NA_HT40MINUS;
445 	if (IEEE80211_IS_CHAN_A(chan))
446 		return HAL_MODE_11A;
447 
448 	/* check for NG_HT before plain G, since IS_CHAN_G includes NG_HT */
449 	if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
450 		return HAL_MODE_11NG_HT20;
451 	if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
452 		return HAL_MODE_11NG_HT40PLUS;
453 	if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
454 		return HAL_MODE_11NG_HT40MINUS;
455 
456 	/*
457 	 * XXX For FreeBSD, will this work correctly given the DYN
458 	 * chan mode (OFDM+CCK dynamic) ? We have pure-G versions DYN-BG..
459 	 */
460 	if (IEEE80211_IS_CHAN_G(chan))
461 		return HAL_MODE_11G;
462 	if (IEEE80211_IS_CHAN_B(chan))
463 		return HAL_MODE_11B;
464 
465 	HALASSERT(0);
466 	return HAL_MODE_11NG_HT20;
467 }
468 
469 
470 typedef enum {
471 	WIRELESS_MODE_11a   = 0,
472 	WIRELESS_MODE_TURBO = 1,
473 	WIRELESS_MODE_11b   = 2,
474 	WIRELESS_MODE_11g   = 3,
475 	WIRELESS_MODE_108g  = 4,
476 
477 	WIRELESS_MODE_MAX
478 } WIRELESS_MODE;
479 
480 static WIRELESS_MODE
481 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
482 {
483 	if (IEEE80211_IS_CHAN_B(chan))
484 		return WIRELESS_MODE_11b;
485 	if (IEEE80211_IS_CHAN_G(chan))
486 		return WIRELESS_MODE_11g;
487 	if (IEEE80211_IS_CHAN_108G(chan))
488 		return WIRELESS_MODE_108g;
489 	if (IEEE80211_IS_CHAN_TURBO(chan))
490 		return WIRELESS_MODE_TURBO;
491 	return WIRELESS_MODE_11a;
492 }
493 
494 /*
495  * Convert between microseconds and core system clocks.
496  */
497                                      /* 11a Turbo  11b  11g  108g */
498 static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
499 
500 #define	CLOCK_FAST_RATE_5GHZ_OFDM	44
501 
502 u_int
503 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
504 {
505 	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
506 	u_int clks;
507 
508 	/* NB: ah_curchan may be null when called attach time */
509 	/* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
510 	if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
511 		clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
512 		if (IEEE80211_IS_CHAN_HT40(c))
513 			clks <<= 1;
514 	} else if (c != AH_NULL) {
515 		clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
516 		if (IEEE80211_IS_CHAN_HT40(c))
517 			clks <<= 1;
518 	} else
519 		clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
520 
521 	/* Compensate for half/quarter rate */
522 	if (c != AH_NULL && IEEE80211_IS_CHAN_HALF(c))
523 		clks = clks / 2;
524 	else if (c != AH_NULL && IEEE80211_IS_CHAN_QUARTER(c))
525 		clks = clks / 4;
526 
527 	return clks;
528 }
529 
530 u_int
531 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
532 {
533 	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
534 	u_int usec;
535 
536 	/* NB: ah_curchan may be null when called attach time */
537 	/* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
538 	if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
539 		usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
540 		if (IEEE80211_IS_CHAN_HT40(c))
541 			usec >>= 1;
542 	} else if (c != AH_NULL) {
543 		usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
544 		if (IEEE80211_IS_CHAN_HT40(c))
545 			usec >>= 1;
546 	} else
547 		usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
548 	return usec;
549 }
550 
551 /*
552  * Setup a h/w rate table's reverse lookup table and
553  * fill in ack durations.  This routine is called for
554  * each rate table returned through the ah_getRateTable
555  * method.  The reverse lookup tables are assumed to be
556  * initialized to zero (or at least the first entry).
557  * We use this as a key that indicates whether or not
558  * we've previously setup the reverse lookup table.
559  *
560  * XXX not reentrant, but shouldn't matter
561  */
562 void
563 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
564 {
565 #define	N(a)	(sizeof(a)/sizeof(a[0]))
566 	int i;
567 
568 	if (rt->rateCodeToIndex[0] != 0)	/* already setup */
569 		return;
570 	for (i = 0; i < N(rt->rateCodeToIndex); i++)
571 		rt->rateCodeToIndex[i] = (uint8_t) -1;
572 	for (i = 0; i < rt->rateCount; i++) {
573 		uint8_t code = rt->info[i].rateCode;
574 		uint8_t cix = rt->info[i].controlRate;
575 
576 		HALASSERT(code < N(rt->rateCodeToIndex));
577 		rt->rateCodeToIndex[code] = i;
578 		HALASSERT((code | rt->info[i].shortPreamble) <
579 		    N(rt->rateCodeToIndex));
580 		rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
581 		/*
582 		 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
583 		 *     depends on whether they are marked as basic rates;
584 		 *     the static tables are setup with an 11b-compatible
585 		 *     2Mb/s rate which will work but is suboptimal
586 		 */
587 		rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
588 			WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
589 		rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
590 			WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
591 	}
592 #undef N
593 }
594 
595 HAL_STATUS
596 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
597 	uint32_t capability, uint32_t *result)
598 {
599 	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
600 
601 	switch (type) {
602 	case HAL_CAP_REG_DMN:		/* regulatory domain */
603 		*result = AH_PRIVATE(ah)->ah_currentRD;
604 		return HAL_OK;
605 	case HAL_CAP_DFS_DMN:		/* DFS Domain */
606 		*result = AH_PRIVATE(ah)->ah_dfsDomain;
607 		return HAL_OK;
608 	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
609 	case HAL_CAP_TKIP_MIC:		/* handle TKIP MIC in hardware */
610 		return HAL_ENOTSUPP;
611 	case HAL_CAP_TKIP_SPLIT:	/* hardware TKIP uses split keys */
612 		return HAL_ENOTSUPP;
613 	case HAL_CAP_PHYCOUNTERS:	/* hardware PHY error counters */
614 		return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
615 	case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
616 		return HAL_ENOTSUPP;
617 	case HAL_CAP_DIVERSITY:		/* hardware supports fast diversity */
618 		return HAL_ENOTSUPP;
619 	case HAL_CAP_KEYCACHE_SIZE:	/* hardware key cache size */
620 		*result =  pCap->halKeyCacheSize;
621 		return HAL_OK;
622 	case HAL_CAP_NUM_TXQUEUES:	/* number of hardware tx queues */
623 		*result = pCap->halTotalQueues;
624 		return HAL_OK;
625 	case HAL_CAP_VEOL:		/* hardware supports virtual EOL */
626 		return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
627 	case HAL_CAP_PSPOLL:		/* hardware PS-Poll support works */
628 		return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
629 	case HAL_CAP_COMPRESSION:
630 		return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
631 	case HAL_CAP_BURST:
632 		return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
633 	case HAL_CAP_FASTFRAME:
634 		return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
635 	case HAL_CAP_DIAG:		/* hardware diagnostic support */
636 		*result = AH_PRIVATE(ah)->ah_diagreg;
637 		return HAL_OK;
638 	case HAL_CAP_TXPOW:		/* global tx power limit  */
639 		switch (capability) {
640 		case 0:			/* facility is supported */
641 			return HAL_OK;
642 		case 1:			/* current limit */
643 			*result = AH_PRIVATE(ah)->ah_powerLimit;
644 			return HAL_OK;
645 		case 2:			/* current max tx power */
646 			*result = AH_PRIVATE(ah)->ah_maxPowerLevel;
647 			return HAL_OK;
648 		case 3:			/* scale factor */
649 			*result = AH_PRIVATE(ah)->ah_tpScale;
650 			return HAL_OK;
651 		}
652 		return HAL_ENOTSUPP;
653 	case HAL_CAP_BSSIDMASK:		/* hardware supports bssid mask */
654 		return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
655 	case HAL_CAP_MCAST_KEYSRCH:	/* multicast frame keycache search */
656 		return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
657 	case HAL_CAP_TSF_ADJUST:	/* hardware has beacon tsf adjust */
658 		return HAL_ENOTSUPP;
659 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
660 		switch (capability) {
661 		case 0:			/* facility is supported */
662 			return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
663 		case 1:			/* current setting */
664 			return AH_PRIVATE(ah)->ah_rfkillEnabled ?
665 				HAL_OK : HAL_ENOTSUPP;
666 		case 2:			/* rfsilent config */
667 			*result = AH_PRIVATE(ah)->ah_rfsilent;
668 			return HAL_OK;
669 		}
670 		return HAL_ENOTSUPP;
671 	case HAL_CAP_11D:
672 		return HAL_OK;
673 
674 	case HAL_CAP_HT:
675 		return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
676 	case HAL_CAP_GTXTO:
677 		return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
678 	case HAL_CAP_FAST_CC:
679 		return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
680 	case HAL_CAP_TX_CHAINMASK:	/* mask of TX chains supported */
681 		*result = pCap->halTxChainMask;
682 		return HAL_OK;
683 	case HAL_CAP_RX_CHAINMASK:	/* mask of RX chains supported */
684 		*result = pCap->halRxChainMask;
685 		return HAL_OK;
686 	case HAL_CAP_NUM_GPIO_PINS:
687 		*result = pCap->halNumGpioPins;
688 		return HAL_OK;
689 	case HAL_CAP_CST:
690 		return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
691 	case HAL_CAP_RTS_AGGR_LIMIT:
692 		*result = pCap->halRtsAggrLimit;
693 		return HAL_OK;
694 	case HAL_CAP_4ADDR_AGGR:
695 		return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
696 	case HAL_CAP_EXT_CHAN_DFS:
697 		return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
698 	case HAL_CAP_RX_STBC:
699 		return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
700 	case HAL_CAP_TX_STBC:
701 		return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
702 	case HAL_CAP_COMBINED_RADAR_RSSI:
703 		return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
704 	case HAL_CAP_AUTO_SLEEP:
705 		return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
706 	case HAL_CAP_MBSSID_AGGR_SUPPORT:
707 		return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
708 	case HAL_CAP_SPLIT_4KB_TRANS:	/* hardware handles descriptors straddling 4k page boundary */
709 		return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
710 	case HAL_CAP_REG_FLAG:
711 		*result = AH_PRIVATE(ah)->ah_currentRDext;
712 		return HAL_OK;
713 	case HAL_CAP_ENHANCED_DMA_SUPPORT:
714 		return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP;
715 	case HAL_CAP_NUM_TXMAPS:
716 		*result = pCap->halNumTxMaps;
717 		return HAL_OK;
718 	case HAL_CAP_TXDESCLEN:
719 		*result = pCap->halTxDescLen;
720 		return HAL_OK;
721 	case HAL_CAP_TXSTATUSLEN:
722 		*result = pCap->halTxStatusLen;
723 		return HAL_OK;
724 	case HAL_CAP_RXSTATUSLEN:
725 		*result = pCap->halRxStatusLen;
726 		return HAL_OK;
727 	case HAL_CAP_RXFIFODEPTH:
728 		switch (capability) {
729 		case HAL_RX_QUEUE_HP:
730 			*result = pCap->halRxHpFifoDepth;
731 			return HAL_OK;
732 		case HAL_RX_QUEUE_LP:
733 			*result = pCap->halRxLpFifoDepth;
734 			return HAL_OK;
735 		default:
736 			return HAL_ENOTSUPP;
737 	}
738 	case HAL_CAP_RXBUFSIZE:
739 	case HAL_CAP_NUM_MR_RETRIES:
740 		*result = pCap->halNumMRRetries;
741 		return HAL_OK;
742 	case HAL_CAP_BT_COEX:
743 		return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
744 	case HAL_CAP_SPECTRAL_SCAN:
745 		return pCap->halSpectralScanSupport ? HAL_OK : HAL_ENOTSUPP;
746 	case HAL_CAP_HT20_SGI:
747 		return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
748 	case HAL_CAP_RXTSTAMP_PREC:	/* rx desc tstamp precision (bits) */
749 		*result = pCap->halTstampPrecision;
750 		return HAL_OK;
751 	case HAL_CAP_ANT_DIV_COMB:	/* AR9285/AR9485 LNA diversity */
752 		return pCap->halAntDivCombSupport ? HAL_OK  : HAL_ENOTSUPP;
753 
754 	case HAL_CAP_ENHANCED_DFS_SUPPORT:
755 		return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
756 
757 	/* FreeBSD-specific entries for now */
758 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
759 		return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
760 	case HAL_CAP_INTRMASK:		/* mask of supported interrupts */
761 		*result = pCap->halIntrMask;
762 		return HAL_OK;
763 	case HAL_CAP_BSSIDMATCH:	/* hardware has disable bssid match */
764 		return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
765 	case HAL_CAP_STREAMS:		/* number of 11n spatial streams */
766 		switch (capability) {
767 		case 0:			/* TX */
768 			*result = pCap->halTxStreams;
769 			return HAL_OK;
770 		case 1:			/* RX */
771 			*result = pCap->halRxStreams;
772 			return HAL_OK;
773 		default:
774 			return HAL_ENOTSUPP;
775 		}
776 	case HAL_CAP_RXDESC_SELFLINK:	/* hardware supports self-linked final RX descriptors correctly */
777 		return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
778 	case HAL_CAP_LONG_RXDESC_TSF:		/* 32 bit TSF in RX descriptor? */
779 		return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP;
780 	case HAL_CAP_BB_READ_WAR:		/* Baseband read WAR */
781 		return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP;
782 	case HAL_CAP_SERIALISE_WAR:		/* PCI register serialisation */
783 		return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP;
784 	case HAL_CAP_MFP:			/* Management frame protection setting */
785 		*result = pCap->halMfpSupport;
786 		return HAL_OK;
787 	case HAL_CAP_RX_LNA_MIXING:	/* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */
788 		return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP;
789 	case HAL_CAP_DO_MYBEACON:	/* Hardware supports filtering my-beacons */
790 		return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP;
791 	default:
792 		return HAL_EINVAL;
793 	}
794 }
795 
796 HAL_BOOL
797 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
798 	uint32_t capability, uint32_t setting, HAL_STATUS *status)
799 {
800 
801 	switch (type) {
802 	case HAL_CAP_TXPOW:
803 		switch (capability) {
804 		case 3:
805 			if (setting <= HAL_TP_SCALE_MIN) {
806 				AH_PRIVATE(ah)->ah_tpScale = setting;
807 				return AH_TRUE;
808 			}
809 			break;
810 		}
811 		break;
812 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
813 		/*
814 		 * NB: allow even if halRfSilentSupport is false
815 		 *     in case the EEPROM is misprogrammed.
816 		 */
817 		switch (capability) {
818 		case 1:			/* current setting */
819 			AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
820 			return AH_TRUE;
821 		case 2:			/* rfsilent config */
822 			/* XXX better done per-chip for validation? */
823 			AH_PRIVATE(ah)->ah_rfsilent = setting;
824 			return AH_TRUE;
825 		}
826 		break;
827 	case HAL_CAP_REG_DMN:		/* regulatory domain */
828 		AH_PRIVATE(ah)->ah_currentRD = setting;
829 		return AH_TRUE;
830 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
831 		AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
832 		return AH_TRUE;
833 	default:
834 		break;
835 	}
836 	if (status)
837 		*status = HAL_EINVAL;
838 	return AH_FALSE;
839 }
840 
841 /*
842  * Common support for getDiagState method.
843  */
844 
845 static u_int
846 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
847 	void *dstbuf, int space)
848 {
849 	uint32_t *dp = dstbuf;
850 	int i;
851 
852 	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
853 		uint32_t r = regs[i].start;
854 		uint32_t e = regs[i].end;
855 		*dp++ = r;
856 		*dp++ = e;
857 		space -= 2*sizeof(uint32_t);
858 		do {
859 			*dp++ = OS_REG_READ(ah, r);
860 			r += sizeof(uint32_t);
861 			space -= sizeof(uint32_t);
862 		} while (r <= e && space >= sizeof(uint32_t));
863 	}
864 	return (char *) dp - (char *) dstbuf;
865 }
866 
867 static void
868 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
869 {
870 	while (space >= sizeof(HAL_REGWRITE)) {
871 		OS_REG_WRITE(ah, regs->addr, regs->value);
872 		regs++, space -= sizeof(HAL_REGWRITE);
873 	}
874 }
875 
876 HAL_BOOL
877 ath_hal_getdiagstate(struct ath_hal *ah, int request,
878 	const void *args, uint32_t argsize,
879 	void **result, uint32_t *resultsize)
880 {
881 	switch (request) {
882 	case HAL_DIAG_REVS:
883 		*result = &AH_PRIVATE(ah)->ah_devid;
884 		*resultsize = sizeof(HAL_REVS);
885 		return AH_TRUE;
886 	case HAL_DIAG_REGS:
887 		*resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
888 		return AH_TRUE;
889 	case HAL_DIAG_SETREGS:
890 		ath_hal_setregs(ah, args, argsize);
891 		*resultsize = 0;
892 		return AH_TRUE;
893 	case HAL_DIAG_FATALERR:
894 		*result = &AH_PRIVATE(ah)->ah_fatalState[0];
895 		*resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
896 		return AH_TRUE;
897 	case HAL_DIAG_EEREAD:
898 		if (argsize != sizeof(uint16_t))
899 			return AH_FALSE;
900 		if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
901 			return AH_FALSE;
902 		*resultsize = sizeof(uint16_t);
903 		return AH_TRUE;
904 #ifdef AH_PRIVATE_DIAG
905 	case HAL_DIAG_SETKEY: {
906 		const HAL_DIAG_KEYVAL *dk;
907 
908 		if (argsize != sizeof(HAL_DIAG_KEYVAL))
909 			return AH_FALSE;
910 		dk = (const HAL_DIAG_KEYVAL *)args;
911 		return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
912 			&dk->dk_keyval, dk->dk_mac, dk->dk_xor);
913 	}
914 	case HAL_DIAG_RESETKEY:
915 		if (argsize != sizeof(uint16_t))
916 			return AH_FALSE;
917 		return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
918 #ifdef AH_SUPPORT_WRITE_EEPROM
919 	case HAL_DIAG_EEWRITE: {
920 		const HAL_DIAG_EEVAL *ee;
921 		if (argsize != sizeof(HAL_DIAG_EEVAL))
922 			return AH_FALSE;
923 		ee = (const HAL_DIAG_EEVAL *)args;
924 		return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
925 	}
926 #endif /* AH_SUPPORT_WRITE_EEPROM */
927 #endif /* AH_PRIVATE_DIAG */
928 	case HAL_DIAG_11NCOMPAT:
929 		if (argsize == 0) {
930 			*resultsize = sizeof(uint32_t);
931 			*((uint32_t *)(*result)) =
932 				AH_PRIVATE(ah)->ah_11nCompat;
933 		} else if (argsize == sizeof(uint32_t)) {
934 			AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
935 		} else
936 			return AH_FALSE;
937 		return AH_TRUE;
938 	}
939 	return AH_FALSE;
940 }
941 
942 /*
943  * Set the properties of the tx queue with the parameters
944  * from qInfo.
945  */
946 HAL_BOOL
947 ath_hal_setTxQProps(struct ath_hal *ah,
948 	HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
949 {
950 	uint32_t cw;
951 
952 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
953 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
954 		    "%s: inactive queue\n", __func__);
955 		return AH_FALSE;
956 	}
957 	/* XXX validate parameters */
958 	qi->tqi_ver = qInfo->tqi_ver;
959 	qi->tqi_subtype = qInfo->tqi_subtype;
960 	qi->tqi_qflags = qInfo->tqi_qflags;
961 	qi->tqi_priority = qInfo->tqi_priority;
962 	if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
963 		qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
964 	else
965 		qi->tqi_aifs = INIT_AIFS;
966 	if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
967 		cw = AH_MIN(qInfo->tqi_cwmin, 1024);
968 		/* make sure that the CWmin is of the form (2^n - 1) */
969 		qi->tqi_cwmin = 1;
970 		while (qi->tqi_cwmin < cw)
971 			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
972 	} else
973 		qi->tqi_cwmin = qInfo->tqi_cwmin;
974 	if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
975 		cw = AH_MIN(qInfo->tqi_cwmax, 1024);
976 		/* make sure that the CWmax is of the form (2^n - 1) */
977 		qi->tqi_cwmax = 1;
978 		while (qi->tqi_cwmax < cw)
979 			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
980 	} else
981 		qi->tqi_cwmax = INIT_CWMAX;
982 	/* Set retry limit values */
983 	if (qInfo->tqi_shretry != 0)
984 		qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
985 	else
986 		qi->tqi_shretry = INIT_SH_RETRY;
987 	if (qInfo->tqi_lgretry != 0)
988 		qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
989 	else
990 		qi->tqi_lgretry = INIT_LG_RETRY;
991 	qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
992 	qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
993 	qi->tqi_burstTime = qInfo->tqi_burstTime;
994 	qi->tqi_readyTime = qInfo->tqi_readyTime;
995 
996 	switch (qInfo->tqi_subtype) {
997 	case HAL_WME_UPSD:
998 		if (qi->tqi_type == HAL_TX_QUEUE_DATA)
999 			qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
1000 		break;
1001 	default:
1002 		break;		/* NB: silence compiler */
1003 	}
1004 	return AH_TRUE;
1005 }
1006 
1007 HAL_BOOL
1008 ath_hal_getTxQProps(struct ath_hal *ah,
1009 	HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
1010 {
1011 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
1012 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
1013 		    "%s: inactive queue\n", __func__);
1014 		return AH_FALSE;
1015 	}
1016 
1017 	qInfo->tqi_qflags = qi->tqi_qflags;
1018 	qInfo->tqi_ver = qi->tqi_ver;
1019 	qInfo->tqi_subtype = qi->tqi_subtype;
1020 	qInfo->tqi_qflags = qi->tqi_qflags;
1021 	qInfo->tqi_priority = qi->tqi_priority;
1022 	qInfo->tqi_aifs = qi->tqi_aifs;
1023 	qInfo->tqi_cwmin = qi->tqi_cwmin;
1024 	qInfo->tqi_cwmax = qi->tqi_cwmax;
1025 	qInfo->tqi_shretry = qi->tqi_shretry;
1026 	qInfo->tqi_lgretry = qi->tqi_lgretry;
1027 	qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
1028 	qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
1029 	qInfo->tqi_burstTime = qi->tqi_burstTime;
1030 	qInfo->tqi_readyTime = qi->tqi_readyTime;
1031 	return AH_TRUE;
1032 }
1033 
1034                                      /* 11a Turbo  11b  11g  108g */
1035 static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
1036 
1037 /*
1038  * Read the current channel noise floor and return.
1039  * If nf cal hasn't finished, channel noise floor should be 0
1040  * and we return a nominal value based on band and frequency.
1041  *
1042  * NB: This is a private routine used by per-chip code to
1043  *     implement the ah_getChanNoise method.
1044  */
1045 int16_t
1046 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
1047 {
1048 	HAL_CHANNEL_INTERNAL *ichan;
1049 
1050 	ichan = ath_hal_checkchannel(ah, chan);
1051 	if (ichan == AH_NULL) {
1052 		HALDEBUG(ah, HAL_DEBUG_NFCAL,
1053 		    "%s: invalid channel %u/0x%x; no mapping\n",
1054 		    __func__, chan->ic_freq, chan->ic_flags);
1055 		return 0;
1056 	}
1057 	if (ichan->rawNoiseFloor == 0) {
1058 		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1059 
1060 		HALASSERT(mode < WIRELESS_MODE_MAX);
1061 		return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
1062 	} else
1063 		return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
1064 }
1065 
1066 /*
1067  * Fetch the current setup of ctl/ext noise floor values.
1068  *
1069  * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
1070  * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
1071  *
1072  * The caller must supply ctl/ext NF arrays which are at least
1073  * AH_MAX_CHAINS entries long.
1074  */
1075 int
1076 ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
1077     const struct ieee80211_channel *chan, int16_t *nf_ctl,
1078     int16_t *nf_ext)
1079 {
1080 #ifdef	AH_SUPPORT_AR5416
1081 	HAL_CHANNEL_INTERNAL *ichan;
1082 	int i;
1083 
1084 	ichan = ath_hal_checkchannel(ah, chan);
1085 	if (ichan == AH_NULL) {
1086 		HALDEBUG(ah, HAL_DEBUG_NFCAL,
1087 		    "%s: invalid channel %u/0x%x; no mapping\n",
1088 		    __func__, chan->ic_freq, chan->ic_flags);
1089 		for (i = 0; i < AH_MAX_CHAINS; i++) {
1090 			nf_ctl[i] = nf_ext[i] = 0;
1091 		}
1092 		return 0;
1093 	}
1094 
1095 	/* Return 0 if there's no valid MIMO values (yet) */
1096 	if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
1097 		for (i = 0; i < AH_MAX_CHAINS; i++) {
1098 			nf_ctl[i] = nf_ext[i] = 0;
1099 		}
1100 		return 0;
1101 	}
1102 	if (ichan->rawNoiseFloor == 0) {
1103 		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1104 		HALASSERT(mode < WIRELESS_MODE_MAX);
1105 		/*
1106 		 * See the comment below - this could cause issues for
1107 		 * stations which have a very low RSSI, below the
1108 		 * 'normalised' NF values in NOISE_FLOOR[].
1109 		 */
1110 		for (i = 0; i < AH_MAX_CHAINS; i++) {
1111 			nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
1112 			    ath_hal_getNfAdjust(ah, ichan);
1113 		}
1114 		return 1;
1115 	} else {
1116 		/*
1117 		 * The value returned here from a MIMO radio is presumed to be
1118 		 * "good enough" as a NF calculation. As RSSI values are calculated
1119 		 * against this, an adjusted NF may be higher than the RSSI value
1120 		 * returned from a vary weak station, resulting in an obscenely
1121 		 * high signal strength calculation being returned.
1122 		 *
1123 		 * This should be re-evaluated at a later date, along with any
1124 		 * signal strength calculations which are made. Quite likely the
1125 		 * RSSI values will need to be adjusted to ensure the calculations
1126 		 * don't "wrap" when RSSI is less than the "adjusted" NF value.
1127 		 * ("Adjust" here is via ichan->noiseFloorAdjust.)
1128 		 */
1129 		for (i = 0; i < AH_MAX_CHAINS; i++) {
1130 			nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
1131 			nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
1132 		}
1133 		return 1;
1134 	}
1135 #else
1136 	return 0;
1137 #endif	/* AH_SUPPORT_AR5416 */
1138 }
1139 
1140 /*
1141  * Process all valid raw noise floors into the dBm noise floor values.
1142  * Though our device has no reference for a dBm noise floor, we perform
1143  * a relative minimization of NF's based on the lowest NF found across a
1144  * channel scan.
1145  */
1146 void
1147 ath_hal_process_noisefloor(struct ath_hal *ah)
1148 {
1149 	HAL_CHANNEL_INTERNAL *c;
1150 	int16_t correct2, correct5;
1151 	int16_t lowest2, lowest5;
1152 	int i;
1153 
1154 	/*
1155 	 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
1156 	 * for statistically recorded NF/channel deviation.
1157 	 */
1158 	correct2 = lowest2 = 0;
1159 	correct5 = lowest5 = 0;
1160 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1161 		WIRELESS_MODE mode;
1162 		int16_t nf;
1163 
1164 		c = &AH_PRIVATE(ah)->ah_channels[i];
1165 		if (c->rawNoiseFloor >= 0)
1166 			continue;
1167 		/* XXX can't identify proper mode */
1168 		mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
1169 		nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
1170 			ath_hal_getNfAdjust(ah, c);
1171 		if (IS_CHAN_5GHZ(c)) {
1172 			if (nf < lowest5) {
1173 				lowest5 = nf;
1174 				correct5 = NOISE_FLOOR[mode] -
1175 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1176 			}
1177 		} else {
1178 			if (nf < lowest2) {
1179 				lowest2 = nf;
1180 				correct2 = NOISE_FLOOR[mode] -
1181 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1182 			}
1183 		}
1184 	}
1185 
1186 	/* Correct the channels to reach the expected NF value */
1187 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1188 		c = &AH_PRIVATE(ah)->ah_channels[i];
1189 		if (c->rawNoiseFloor >= 0)
1190 			continue;
1191 		/* Apply correction factor */
1192 		c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
1193 			(IS_CHAN_5GHZ(c) ? correct5 : correct2);
1194 		HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
1195 		    c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
1196 	}
1197 }
1198 
1199 /*
1200  * INI support routines.
1201  */
1202 
1203 int
1204 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1205 	int col, int regWr)
1206 {
1207 	int r;
1208 
1209 	HALASSERT(col < ia->cols);
1210 	for (r = 0; r < ia->rows; r++) {
1211 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1212 		    HAL_INI_VAL(ia, r, col));
1213 
1214 		/* Analog shift register delay seems needed for Merlin - PR kern/154220 */
1215 		if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
1216 			OS_DELAY(100);
1217 
1218 		DMA_YIELD(regWr);
1219 	}
1220 	return regWr;
1221 }
1222 
1223 void
1224 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1225 {
1226 	int r;
1227 
1228 	HALASSERT(col < ia->cols);
1229 	for (r = 0; r < ia->rows; r++)
1230 		data[r] = HAL_INI_VAL(ia, r, col);
1231 }
1232 
1233 int
1234 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1235 	const uint32_t data[], int regWr)
1236 {
1237 	int r;
1238 
1239 	for (r = 0; r < ia->rows; r++) {
1240 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1241 		DMA_YIELD(regWr);
1242 	}
1243 	return regWr;
1244 }
1245 
1246 /*
1247  * These are EEPROM board related routines which should likely live in
1248  * a helper library of some sort.
1249  */
1250 
1251 /**************************************************************
1252  * ath_ee_getLowerUppderIndex
1253  *
1254  * Return indices surrounding the value in sorted integer lists.
1255  * Requirement: the input list must be monotonically increasing
1256  *     and populated up to the list size
1257  * Returns: match is set if an index in the array matches exactly
1258  *     or a the target is before or after the range of the array.
1259  */
1260 HAL_BOOL
1261 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1262                    uint16_t *indexL, uint16_t *indexR)
1263 {
1264     uint16_t i;
1265 
1266     /*
1267      * Check first and last elements for beyond ordered array cases.
1268      */
1269     if (target <= pList[0]) {
1270         *indexL = *indexR = 0;
1271         return AH_TRUE;
1272     }
1273     if (target >= pList[listSize-1]) {
1274         *indexL = *indexR = (uint16_t)(listSize - 1);
1275         return AH_TRUE;
1276     }
1277 
1278     /* look for value being near or between 2 values in list */
1279     for (i = 0; i < listSize - 1; i++) {
1280         /*
1281          * If value is close to the current value of the list
1282          * then target is not between values, it is one of the values
1283          */
1284         if (pList[i] == target) {
1285             *indexL = *indexR = i;
1286             return AH_TRUE;
1287         }
1288         /*
1289          * Look for value being between current value and next value
1290          * if so return these 2 values
1291          */
1292         if (target < pList[i + 1]) {
1293             *indexL = i;
1294             *indexR = (uint16_t)(i + 1);
1295             return AH_FALSE;
1296         }
1297     }
1298     HALASSERT(0);
1299     *indexL = *indexR = 0;
1300     return AH_FALSE;
1301 }
1302 
1303 /**************************************************************
1304  * ath_ee_FillVpdTable
1305  *
1306  * Fill the Vpdlist for indices Pmax-Pmin
1307  * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1308  */
1309 HAL_BOOL
1310 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1311                    uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1312 {
1313     uint16_t  i, k;
1314     uint8_t   currPwr = pwrMin;
1315     uint16_t  idxL, idxR;
1316 
1317     HALASSERT(pwrMax > pwrMin);
1318     for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1319         ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1320                            &(idxL), &(idxR));
1321         if (idxR < 1)
1322             idxR = 1;           /* extrapolate below */
1323         if (idxL == numIntercepts - 1)
1324             idxL = (uint16_t)(numIntercepts - 2);   /* extrapolate above */
1325         if (pPwrList[idxL] == pPwrList[idxR])
1326             k = pVpdList[idxL];
1327         else
1328             k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1329                   (pPwrList[idxR] - pPwrList[idxL]) );
1330         HALASSERT(k < 256);
1331         pRetVpdList[i] = (uint8_t)k;
1332         currPwr += 2;               /* half dB steps */
1333     }
1334 
1335     return AH_TRUE;
1336 }
1337 
1338 /**************************************************************************
1339  * ath_ee_interpolate
1340  *
1341  * Returns signed interpolated or the scaled up interpolated value
1342  */
1343 int16_t
1344 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1345             int16_t targetLeft, int16_t targetRight)
1346 {
1347     int16_t rv;
1348 
1349     if (srcRight == srcLeft) {
1350         rv = targetLeft;
1351     } else {
1352         rv = (int16_t)( ((target - srcLeft) * targetRight +
1353               (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1354     }
1355     return rv;
1356 }
1357 
1358 /*
1359  * Adjust the TSF.
1360  */
1361 void
1362 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
1363 {
1364 	/* XXX handle wrap/overflow */
1365 	OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
1366 }
1367 
1368 /*
1369  * Enable or disable CCA.
1370  */
1371 void
1372 ath_hal_setcca(struct ath_hal *ah, int ena)
1373 {
1374 	/*
1375 	 * NB: fill me in; this is not provided by default because disabling
1376 	 *     CCA in most locales violates regulatory.
1377 	 */
1378 }
1379 
1380 /*
1381  * Get CCA setting.
1382  */
1383 int
1384 ath_hal_getcca(struct ath_hal *ah)
1385 {
1386 	u_int32_t diag;
1387 	if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
1388 		return 1;
1389 	return ((diag & 0x500000) == 0);
1390 }
1391 
1392 /*
1393  * This routine is only needed when supporting EEPROM-in-RAM setups
1394  * (eg embedded SoCs and on-board PCI/PCIe devices.)
1395  */
1396 /* NB: This is in 16 bit words; not bytes */
1397 /* XXX This doesn't belong here!  */
1398 #define ATH_DATA_EEPROM_SIZE    2048
1399 
1400 HAL_BOOL
1401 ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data)
1402 {
1403 	if (ah->ah_eepromdata == AH_NULL) {
1404 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__);
1405 		return AH_FALSE;
1406 	}
1407 	if (off > ATH_DATA_EEPROM_SIZE) {
1408 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n",
1409 		    __func__, off, ATH_DATA_EEPROM_SIZE);
1410 		return AH_FALSE;
1411 	}
1412 	(*data) = ah->ah_eepromdata[off];
1413 	return AH_TRUE;
1414 }
1415 
1416 /*
1417  * Do a 2GHz specific MHz->IEEE based on the hardware
1418  * frequency.
1419  *
1420  * This is the unmapped frequency which is programmed into the hardware.
1421  */
1422 int
1423 ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
1424 {
1425 
1426 	if (ichan->channel == 2484)
1427 		return 14;
1428 	if (ichan->channel < 2484)
1429 		return ((int) ichan->channel - 2407) / 5;
1430 	else
1431 		return 15 + ((ichan->channel - 2512) / 20);
1432 }
1433