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