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