ah.c revision 217624
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 217624 2011-01-20 07:56:09Z 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/*
238 * Compute the time to transmit a frame of length frameLen bytes
239 * using the specified rate, phy, and short preamble setting.
240 */
241uint16_t
242ath_hal_computetxtime(struct ath_hal *ah,
243	const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
244	HAL_BOOL shortPreamble)
245{
246	uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
247	uint32_t kbps;
248
249	kbps = rates->info[rateix].rateKbps;
250	/*
251	 * index can be invalid duting dynamic Turbo transitions.
252	 * XXX
253	 */
254	if (kbps == 0)
255		return 0;
256	switch (rates->info[rateix].phy) {
257	case IEEE80211_T_CCK:
258		phyTime		= CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
259		if (shortPreamble && rates->info[rateix].shortPreamble)
260			phyTime >>= 1;
261		numBits		= frameLen << 3;
262		txTime		= CCK_SIFS_TIME + phyTime
263				+ ((numBits * 1000)/kbps);
264		break;
265	case IEEE80211_T_OFDM:
266		bitsPerSymbol	= (kbps * OFDM_SYMBOL_TIME) / 1000;
267		HALASSERT(bitsPerSymbol != 0);
268
269		numBits		= OFDM_PLCP_BITS + (frameLen << 3);
270		numSymbols	= howmany(numBits, bitsPerSymbol);
271		txTime		= OFDM_SIFS_TIME
272				+ OFDM_PREAMBLE_TIME
273				+ (numSymbols * OFDM_SYMBOL_TIME);
274		break;
275	case IEEE80211_T_OFDM_HALF:
276		bitsPerSymbol	= (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
277		HALASSERT(bitsPerSymbol != 0);
278
279		numBits		= OFDM_HALF_PLCP_BITS + (frameLen << 3);
280		numSymbols	= howmany(numBits, bitsPerSymbol);
281		txTime		= OFDM_HALF_SIFS_TIME
282				+ OFDM_HALF_PREAMBLE_TIME
283				+ (numSymbols * OFDM_HALF_SYMBOL_TIME);
284		break;
285	case IEEE80211_T_OFDM_QUARTER:
286		bitsPerSymbol	= (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
287		HALASSERT(bitsPerSymbol != 0);
288
289		numBits		= OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
290		numSymbols	= howmany(numBits, bitsPerSymbol);
291		txTime		= OFDM_QUARTER_SIFS_TIME
292				+ OFDM_QUARTER_PREAMBLE_TIME
293				+ (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
294		break;
295	case IEEE80211_T_TURBO:
296		bitsPerSymbol	= (kbps * TURBO_SYMBOL_TIME) / 1000;
297		HALASSERT(bitsPerSymbol != 0);
298
299		numBits		= TURBO_PLCP_BITS + (frameLen << 3);
300		numSymbols	= howmany(numBits, bitsPerSymbol);
301		txTime		= TURBO_SIFS_TIME
302				+ TURBO_PREAMBLE_TIME
303				+ (numSymbols * TURBO_SYMBOL_TIME);
304		break;
305	default:
306		HALDEBUG(ah, HAL_DEBUG_PHYIO,
307		    "%s: unknown phy %u (rate ix %u)\n",
308		    __func__, rates->info[rateix].phy, rateix);
309		txTime = 0;
310		break;
311	}
312	return txTime;
313}
314
315typedef enum {
316	WIRELESS_MODE_11a   = 0,
317	WIRELESS_MODE_TURBO = 1,
318	WIRELESS_MODE_11b   = 2,
319	WIRELESS_MODE_11g   = 3,
320	WIRELESS_MODE_108g  = 4,
321
322	WIRELESS_MODE_MAX
323} WIRELESS_MODE;
324
325static WIRELESS_MODE
326ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
327{
328	if (IEEE80211_IS_CHAN_B(chan))
329		return WIRELESS_MODE_11b;
330	if (IEEE80211_IS_CHAN_G(chan))
331		return WIRELESS_MODE_11g;
332	if (IEEE80211_IS_CHAN_108G(chan))
333		return WIRELESS_MODE_108g;
334	if (IEEE80211_IS_CHAN_TURBO(chan))
335		return WIRELESS_MODE_TURBO;
336	return WIRELESS_MODE_11a;
337}
338
339/*
340 * Convert between microseconds and core system clocks.
341 */
342                                     /* 11a Turbo  11b  11g  108g */
343static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
344
345u_int
346ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
347{
348	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
349	u_int clks;
350
351	/* NB: ah_curchan may be null when called attach time */
352	if (c != AH_NULL) {
353		clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
354		if (IEEE80211_IS_CHAN_HT40(c))
355			clks <<= 1;
356	} else
357		clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
358	return clks;
359}
360
361u_int
362ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
363{
364	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
365	u_int usec;
366
367	/* NB: ah_curchan may be null when called attach time */
368	if (c != AH_NULL) {
369		usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
370		if (IEEE80211_IS_CHAN_HT40(c))
371			usec >>= 1;
372	} else
373		usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
374	return usec;
375}
376
377/*
378 * Setup a h/w rate table's reverse lookup table and
379 * fill in ack durations.  This routine is called for
380 * each rate table returned through the ah_getRateTable
381 * method.  The reverse lookup tables are assumed to be
382 * initialized to zero (or at least the first entry).
383 * We use this as a key that indicates whether or not
384 * we've previously setup the reverse lookup table.
385 *
386 * XXX not reentrant, but shouldn't matter
387 */
388void
389ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
390{
391#define	N(a)	(sizeof(a)/sizeof(a[0]))
392	int i;
393
394	if (rt->rateCodeToIndex[0] != 0)	/* already setup */
395		return;
396	for (i = 0; i < N(rt->rateCodeToIndex); i++)
397		rt->rateCodeToIndex[i] = (uint8_t) -1;
398	for (i = 0; i < rt->rateCount; i++) {
399		uint8_t code = rt->info[i].rateCode;
400		uint8_t cix = rt->info[i].controlRate;
401
402		HALASSERT(code < N(rt->rateCodeToIndex));
403		rt->rateCodeToIndex[code] = i;
404		HALASSERT((code | rt->info[i].shortPreamble) <
405		    N(rt->rateCodeToIndex));
406		rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
407		/*
408		 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
409		 *     depends on whether they are marked as basic rates;
410		 *     the static tables are setup with an 11b-compatible
411		 *     2Mb/s rate which will work but is suboptimal
412		 */
413		rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
414			WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
415		rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
416			WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
417	}
418#undef N
419}
420
421HAL_STATUS
422ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
423	uint32_t capability, uint32_t *result)
424{
425	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
426
427	switch (type) {
428	case HAL_CAP_REG_DMN:		/* regulatory domain */
429		*result = AH_PRIVATE(ah)->ah_currentRD;
430		return HAL_OK;
431	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
432	case HAL_CAP_TKIP_MIC:		/* handle TKIP MIC in hardware */
433		return HAL_ENOTSUPP;
434	case HAL_CAP_TKIP_SPLIT:	/* hardware TKIP uses split keys */
435		return HAL_ENOTSUPP;
436	case HAL_CAP_PHYCOUNTERS:	/* hardware PHY error counters */
437		return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
438	case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
439		return HAL_ENOTSUPP;
440	case HAL_CAP_DIVERSITY:		/* hardware supports fast diversity */
441		return HAL_ENOTSUPP;
442	case HAL_CAP_KEYCACHE_SIZE:	/* hardware key cache size */
443		*result =  pCap->halKeyCacheSize;
444		return HAL_OK;
445	case HAL_CAP_NUM_TXQUEUES:	/* number of hardware tx queues */
446		*result = pCap->halTotalQueues;
447		return HAL_OK;
448	case HAL_CAP_VEOL:		/* hardware supports virtual EOL */
449		return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
450	case HAL_CAP_PSPOLL:		/* hardware PS-Poll support works */
451		return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
452	case HAL_CAP_COMPRESSION:
453		return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
454	case HAL_CAP_BURST:
455		return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
456	case HAL_CAP_FASTFRAME:
457		return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
458	case HAL_CAP_DIAG:		/* hardware diagnostic support */
459		*result = AH_PRIVATE(ah)->ah_diagreg;
460		return HAL_OK;
461	case HAL_CAP_TXPOW:		/* global tx power limit  */
462		switch (capability) {
463		case 0:			/* facility is supported */
464			return HAL_OK;
465		case 1:			/* current limit */
466			*result = AH_PRIVATE(ah)->ah_powerLimit;
467			return HAL_OK;
468		case 2:			/* current max tx power */
469			*result = AH_PRIVATE(ah)->ah_maxPowerLevel;
470			return HAL_OK;
471		case 3:			/* scale factor */
472			*result = AH_PRIVATE(ah)->ah_tpScale;
473			return HAL_OK;
474		}
475		return HAL_ENOTSUPP;
476	case HAL_CAP_BSSIDMASK:		/* hardware supports bssid mask */
477		return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
478	case HAL_CAP_MCAST_KEYSRCH:	/* multicast frame keycache search */
479		return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
480	case HAL_CAP_TSF_ADJUST:	/* hardware has beacon tsf adjust */
481		return HAL_ENOTSUPP;
482	case HAL_CAP_RFSILENT:		/* rfsilent support  */
483		switch (capability) {
484		case 0:			/* facility is supported */
485			return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
486		case 1:			/* current setting */
487			return AH_PRIVATE(ah)->ah_rfkillEnabled ?
488				HAL_OK : HAL_ENOTSUPP;
489		case 2:			/* rfsilent config */
490			*result = AH_PRIVATE(ah)->ah_rfsilent;
491			return HAL_OK;
492		}
493		return HAL_ENOTSUPP;
494	case HAL_CAP_11D:
495		return HAL_OK;
496	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
497		return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
498	case HAL_CAP_HT:
499		return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
500	case HAL_CAP_TX_CHAINMASK:	/* mask of TX chains supported */
501		*result = pCap->halTxChainMask;
502		return HAL_OK;
503	case HAL_CAP_RX_CHAINMASK:	/* mask of RX chains supported */
504		*result = pCap->halRxChainMask;
505		return HAL_OK;
506	case HAL_CAP_RXTSTAMP_PREC:	/* rx desc tstamp precision (bits) */
507		*result = pCap->halTstampPrecision;
508		return HAL_OK;
509	case HAL_CAP_INTRMASK:		/* mask of supported interrupts */
510		*result = pCap->halIntrMask;
511		return HAL_OK;
512	case HAL_CAP_BSSIDMATCH:	/* hardware has disable bssid match */
513		return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
514	default:
515		return HAL_EINVAL;
516	}
517}
518
519HAL_BOOL
520ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
521	uint32_t capability, uint32_t setting, HAL_STATUS *status)
522{
523
524	switch (type) {
525	case HAL_CAP_TXPOW:
526		switch (capability) {
527		case 3:
528			if (setting <= HAL_TP_SCALE_MIN) {
529				AH_PRIVATE(ah)->ah_tpScale = setting;
530				return AH_TRUE;
531			}
532			break;
533		}
534		break;
535	case HAL_CAP_RFSILENT:		/* rfsilent support  */
536		/*
537		 * NB: allow even if halRfSilentSupport is false
538		 *     in case the EEPROM is misprogrammed.
539		 */
540		switch (capability) {
541		case 1:			/* current setting */
542			AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
543			return AH_TRUE;
544		case 2:			/* rfsilent config */
545			/* XXX better done per-chip for validation? */
546			AH_PRIVATE(ah)->ah_rfsilent = setting;
547			return AH_TRUE;
548		}
549		break;
550	case HAL_CAP_REG_DMN:		/* regulatory domain */
551		AH_PRIVATE(ah)->ah_currentRD = setting;
552		return AH_TRUE;
553	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
554		AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
555		return AH_TRUE;
556	default:
557		break;
558	}
559	if (status)
560		*status = HAL_EINVAL;
561	return AH_FALSE;
562}
563
564/*
565 * Common support for getDiagState method.
566 */
567
568static u_int
569ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
570	void *dstbuf, int space)
571{
572	uint32_t *dp = dstbuf;
573	int i;
574
575	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
576		u_int r = regs[i].start;
577		u_int e = regs[i].end;
578		*dp++ = (r<<16) | e;
579		space -= sizeof(uint32_t);
580		do {
581			*dp++ = OS_REG_READ(ah, r);
582			r += sizeof(uint32_t);
583			space -= sizeof(uint32_t);
584		} while (r <= e && space >= sizeof(uint32_t));
585	}
586	return (char *) dp - (char *) dstbuf;
587}
588
589static void
590ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
591{
592	while (space >= sizeof(HAL_REGWRITE)) {
593		OS_REG_WRITE(ah, regs->addr, regs->value);
594		regs++, space -= sizeof(HAL_REGWRITE);
595	}
596}
597
598HAL_BOOL
599ath_hal_getdiagstate(struct ath_hal *ah, int request,
600	const void *args, uint32_t argsize,
601	void **result, uint32_t *resultsize)
602{
603	switch (request) {
604	case HAL_DIAG_REVS:
605		*result = &AH_PRIVATE(ah)->ah_devid;
606		*resultsize = sizeof(HAL_REVS);
607		return AH_TRUE;
608	case HAL_DIAG_REGS:
609		*resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
610		return AH_TRUE;
611	case HAL_DIAG_SETREGS:
612		ath_hal_setregs(ah, args, argsize);
613		*resultsize = 0;
614		return AH_TRUE;
615	case HAL_DIAG_FATALERR:
616		*result = &AH_PRIVATE(ah)->ah_fatalState[0];
617		*resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
618		return AH_TRUE;
619	case HAL_DIAG_EEREAD:
620		if (argsize != sizeof(uint16_t))
621			return AH_FALSE;
622		if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
623			return AH_FALSE;
624		*resultsize = sizeof(uint16_t);
625		return AH_TRUE;
626#ifdef AH_PRIVATE_DIAG
627	case HAL_DIAG_SETKEY: {
628		const HAL_DIAG_KEYVAL *dk;
629
630		if (argsize != sizeof(HAL_DIAG_KEYVAL))
631			return AH_FALSE;
632		dk = (const HAL_DIAG_KEYVAL *)args;
633		return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
634			&dk->dk_keyval, dk->dk_mac, dk->dk_xor);
635	}
636	case HAL_DIAG_RESETKEY:
637		if (argsize != sizeof(uint16_t))
638			return AH_FALSE;
639		return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
640#ifdef AH_SUPPORT_WRITE_EEPROM
641	case HAL_DIAG_EEWRITE: {
642		const HAL_DIAG_EEVAL *ee;
643		if (argsize != sizeof(HAL_DIAG_EEVAL))
644			return AH_FALSE;
645		ee = (const HAL_DIAG_EEVAL *)args;
646		return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
647	}
648#endif /* AH_SUPPORT_WRITE_EEPROM */
649#endif /* AH_PRIVATE_DIAG */
650	case HAL_DIAG_11NCOMPAT:
651		if (argsize == 0) {
652			*resultsize = sizeof(uint32_t);
653			*((uint32_t *)(*result)) =
654				AH_PRIVATE(ah)->ah_11nCompat;
655		} else if (argsize == sizeof(uint32_t)) {
656			AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
657		} else
658			return AH_FALSE;
659		return AH_TRUE;
660	}
661	return AH_FALSE;
662}
663
664/*
665 * Set the properties of the tx queue with the parameters
666 * from qInfo.
667 */
668HAL_BOOL
669ath_hal_setTxQProps(struct ath_hal *ah,
670	HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
671{
672	uint32_t cw;
673
674	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
675		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
676		    "%s: inactive queue\n", __func__);
677		return AH_FALSE;
678	}
679	/* XXX validate parameters */
680	qi->tqi_ver = qInfo->tqi_ver;
681	qi->tqi_subtype = qInfo->tqi_subtype;
682	qi->tqi_qflags = qInfo->tqi_qflags;
683	qi->tqi_priority = qInfo->tqi_priority;
684	if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
685		qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
686	else
687		qi->tqi_aifs = INIT_AIFS;
688	if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
689		cw = AH_MIN(qInfo->tqi_cwmin, 1024);
690		/* make sure that the CWmin is of the form (2^n - 1) */
691		qi->tqi_cwmin = 1;
692		while (qi->tqi_cwmin < cw)
693			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
694	} else
695		qi->tqi_cwmin = qInfo->tqi_cwmin;
696	if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
697		cw = AH_MIN(qInfo->tqi_cwmax, 1024);
698		/* make sure that the CWmax is of the form (2^n - 1) */
699		qi->tqi_cwmax = 1;
700		while (qi->tqi_cwmax < cw)
701			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
702	} else
703		qi->tqi_cwmax = INIT_CWMAX;
704	/* Set retry limit values */
705	if (qInfo->tqi_shretry != 0)
706		qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
707	else
708		qi->tqi_shretry = INIT_SH_RETRY;
709	if (qInfo->tqi_lgretry != 0)
710		qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
711	else
712		qi->tqi_lgretry = INIT_LG_RETRY;
713	qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
714	qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
715	qi->tqi_burstTime = qInfo->tqi_burstTime;
716	qi->tqi_readyTime = qInfo->tqi_readyTime;
717
718	switch (qInfo->tqi_subtype) {
719	case HAL_WME_UPSD:
720		if (qi->tqi_type == HAL_TX_QUEUE_DATA)
721			qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
722		break;
723	default:
724		break;		/* NB: silence compiler */
725	}
726	return AH_TRUE;
727}
728
729HAL_BOOL
730ath_hal_getTxQProps(struct ath_hal *ah,
731	HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
732{
733	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
734		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
735		    "%s: inactive queue\n", __func__);
736		return AH_FALSE;
737	}
738
739	qInfo->tqi_qflags = qi->tqi_qflags;
740	qInfo->tqi_ver = qi->tqi_ver;
741	qInfo->tqi_subtype = qi->tqi_subtype;
742	qInfo->tqi_qflags = qi->tqi_qflags;
743	qInfo->tqi_priority = qi->tqi_priority;
744	qInfo->tqi_aifs = qi->tqi_aifs;
745	qInfo->tqi_cwmin = qi->tqi_cwmin;
746	qInfo->tqi_cwmax = qi->tqi_cwmax;
747	qInfo->tqi_shretry = qi->tqi_shretry;
748	qInfo->tqi_lgretry = qi->tqi_lgretry;
749	qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
750	qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
751	qInfo->tqi_burstTime = qi->tqi_burstTime;
752	qInfo->tqi_readyTime = qi->tqi_readyTime;
753	return AH_TRUE;
754}
755
756                                     /* 11a Turbo  11b  11g  108g */
757static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
758
759/*
760 * Read the current channel noise floor and return.
761 * If nf cal hasn't finished, channel noise floor should be 0
762 * and we return a nominal value based on band and frequency.
763 *
764 * NB: This is a private routine used by per-chip code to
765 *     implement the ah_getChanNoise method.
766 */
767int16_t
768ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
769{
770	HAL_CHANNEL_INTERNAL *ichan;
771
772	ichan = ath_hal_checkchannel(ah, chan);
773	if (ichan == AH_NULL) {
774		HALDEBUG(ah, HAL_DEBUG_NFCAL,
775		    "%s: invalid channel %u/0x%x; no mapping\n",
776		    __func__, chan->ic_freq, chan->ic_flags);
777		return 0;
778	}
779	if (ichan->rawNoiseFloor == 0) {
780		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
781
782		HALASSERT(mode < WIRELESS_MODE_MAX);
783		return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
784	} else
785		return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
786}
787
788/*
789 * Process all valid raw noise floors into the dBm noise floor values.
790 * Though our device has no reference for a dBm noise floor, we perform
791 * a relative minimization of NF's based on the lowest NF found across a
792 * channel scan.
793 */
794void
795ath_hal_process_noisefloor(struct ath_hal *ah)
796{
797	HAL_CHANNEL_INTERNAL *c;
798	int16_t correct2, correct5;
799	int16_t lowest2, lowest5;
800	int i;
801
802	/*
803	 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
804	 * for statistically recorded NF/channel deviation.
805	 */
806	correct2 = lowest2 = 0;
807	correct5 = lowest5 = 0;
808	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
809		WIRELESS_MODE mode;
810		int16_t nf;
811
812		c = &AH_PRIVATE(ah)->ah_channels[i];
813		if (c->rawNoiseFloor >= 0)
814			continue;
815		/* XXX can't identify proper mode */
816		mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
817		nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
818			ath_hal_getNfAdjust(ah, c);
819		if (IS_CHAN_5GHZ(c)) {
820			if (nf < lowest5) {
821				lowest5 = nf;
822				correct5 = NOISE_FLOOR[mode] -
823				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
824			}
825		} else {
826			if (nf < lowest2) {
827				lowest2 = nf;
828				correct2 = NOISE_FLOOR[mode] -
829				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
830			}
831		}
832	}
833
834	/* Correct the channels to reach the expected NF value */
835	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
836		c = &AH_PRIVATE(ah)->ah_channels[i];
837		if (c->rawNoiseFloor >= 0)
838			continue;
839		/* Apply correction factor */
840		c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
841			(IS_CHAN_5GHZ(c) ? correct5 : correct2);
842		HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
843		    c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
844	}
845}
846
847/*
848 * INI support routines.
849 */
850
851int
852ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
853	int col, int regWr)
854{
855	int r;
856
857	HALASSERT(col < ia->cols);
858	for (r = 0; r < ia->rows; r++) {
859		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
860		    HAL_INI_VAL(ia, r, col));
861		DMA_YIELD(regWr);
862	}
863	return regWr;
864}
865
866void
867ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
868{
869	int r;
870
871	HALASSERT(col < ia->cols);
872	for (r = 0; r < ia->rows; r++)
873		data[r] = HAL_INI_VAL(ia, r, col);
874}
875
876int
877ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
878	const uint32_t data[], int regWr)
879{
880	int r;
881
882	for (r = 0; r < ia->rows; r++) {
883		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
884		DMA_YIELD(regWr);
885	}
886	return regWr;
887}
888