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