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