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