ah.c revision 188773
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 188773 2009-02-19 04:24:22Z sam $
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24
25/* linker set of registered chips */
26OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
27
28/*
29 * Check the set of registered chips to see if any recognize
30 * the device as one they can support.
31 */
32const char*
33ath_hal_probe(uint16_t vendorid, uint16_t devid)
34{
35	struct ath_hal_chip * const *pchip;
36
37	OS_SET_FOREACH(pchip, ah_chips) {
38		const char *name = (*pchip)->probe(vendorid, devid);
39		if (name != AH_NULL)
40			return name;
41	}
42	return AH_NULL;
43}
44
45/*
46 * Attach detects device chip revisions, initializes the hwLayer
47 * function list, reads EEPROM information,
48 * selects reset vectors, and performs a short self test.
49 * Any failures will return an error that should cause a hardware
50 * disable.
51 */
52struct ath_hal*
53ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
54	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
55{
56	struct ath_hal_chip * const *pchip;
57
58	OS_SET_FOREACH(pchip, ah_chips) {
59		struct ath_hal_chip *chip = *pchip;
60		struct ath_hal *ah;
61
62		/* XXX don't have vendorid, assume atheros one works */
63		if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
64			continue;
65		ah = chip->attach(devid, sc, st, sh, error);
66		if (ah != AH_NULL) {
67			/* copy back private state to public area */
68			ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
69			ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
70			ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
71			ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
72			ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
73			ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
74			ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
75			return ah;
76		}
77	}
78	return AH_NULL;
79}
80
81/*
82 * Return the mask of available modes based on the hardware capabilities.
83 */
84u_int
85ath_hal_getwirelessmodes(struct ath_hal*ah)
86{
87	return ath_hal_getWirelessModes(ah);
88}
89
90/* linker set of registered RF backends */
91OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
92
93/*
94 * Check the set of registered RF backends to see if
95 * any recognize the device as one they can support.
96 */
97struct ath_hal_rf *
98ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
99{
100	struct ath_hal_rf * const *prf;
101
102	OS_SET_FOREACH(prf, ah_rfs) {
103		struct ath_hal_rf *rf = *prf;
104		if (rf->probe(ah))
105			return rf;
106	}
107	*ecode = HAL_ENOTSUPP;
108	return AH_NULL;
109}
110
111/*
112 * Poll the register looking for a specific value.
113 */
114HAL_BOOL
115ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
116{
117#define	AH_TIMEOUT	1000
118	int i;
119
120	for (i = 0; i < AH_TIMEOUT; i++) {
121		if ((OS_REG_READ(ah, reg) & mask) == val)
122			return AH_TRUE;
123		OS_DELAY(10);
124	}
125	HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
126	    "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
127	    __func__, reg, OS_REG_READ(ah, reg), mask, val);
128	return AH_FALSE;
129#undef AH_TIMEOUT
130}
131
132/*
133 * Reverse the bits starting at the low bit for a value of
134 * bit_count in size
135 */
136uint32_t
137ath_hal_reverseBits(uint32_t val, uint32_t n)
138{
139	uint32_t retval;
140	int i;
141
142	for (i = 0, retval = 0; i < n; i++) {
143		retval = (retval << 1) | (val & 1);
144		val >>= 1;
145	}
146	return retval;
147}
148
149/*
150 * Compute the time to transmit a frame of length frameLen bytes
151 * using the specified rate, phy, and short preamble setting.
152 */
153uint16_t
154ath_hal_computetxtime(struct ath_hal *ah,
155	const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
156	HAL_BOOL shortPreamble)
157{
158	uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
159	uint32_t kbps;
160
161	kbps = rates->info[rateix].rateKbps;
162	/*
163	 * index can be invalid duting dynamic Turbo transitions.
164	 * XXX
165	 */
166	if (kbps == 0)
167		return 0;
168	switch (rates->info[rateix].phy) {
169	case IEEE80211_T_CCK:
170		phyTime		= CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
171		if (shortPreamble && rates->info[rateix].shortPreamble)
172			phyTime >>= 1;
173		numBits		= frameLen << 3;
174		txTime		= CCK_SIFS_TIME + phyTime
175				+ ((numBits * 1000)/kbps);
176		break;
177	case IEEE80211_T_OFDM:
178		bitsPerSymbol	= (kbps * OFDM_SYMBOL_TIME) / 1000;
179		HALASSERT(bitsPerSymbol != 0);
180
181		numBits		= OFDM_PLCP_BITS + (frameLen << 3);
182		numSymbols	= howmany(numBits, bitsPerSymbol);
183		txTime		= OFDM_SIFS_TIME
184				+ OFDM_PREAMBLE_TIME
185				+ (numSymbols * OFDM_SYMBOL_TIME);
186		break;
187	case IEEE80211_T_OFDM_HALF:
188		bitsPerSymbol	= (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
189		HALASSERT(bitsPerSymbol != 0);
190
191		numBits		= OFDM_HALF_PLCP_BITS + (frameLen << 3);
192		numSymbols	= howmany(numBits, bitsPerSymbol);
193		txTime		= OFDM_HALF_SIFS_TIME
194				+ OFDM_HALF_PREAMBLE_TIME
195				+ (numSymbols * OFDM_HALF_SYMBOL_TIME);
196		break;
197	case IEEE80211_T_OFDM_QUARTER:
198		bitsPerSymbol	= (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
199		HALASSERT(bitsPerSymbol != 0);
200
201		numBits		= OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
202		numSymbols	= howmany(numBits, bitsPerSymbol);
203		txTime		= OFDM_QUARTER_SIFS_TIME
204				+ OFDM_QUARTER_PREAMBLE_TIME
205				+ (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
206		break;
207	case IEEE80211_T_TURBO:
208		/* we still save OFDM rates in kbps - so double them */
209		bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
210		HALASSERT(bitsPerSymbol != 0);
211
212		numBits		= TURBO_PLCP_BITS + (frameLen << 3);
213		numSymbols	= howmany(numBits, bitsPerSymbol);
214		txTime		= TURBO_SIFS_TIME
215				+ TURBO_PREAMBLE_TIME
216				+ (numSymbols * TURBO_SYMBOL_TIME);
217		break;
218	default:
219		HALDEBUG(ah, HAL_DEBUG_PHYIO,
220		    "%s: unknown phy %u (rate ix %u)\n",
221		    __func__, rates->info[rateix].phy, rateix);
222		txTime = 0;
223		break;
224	}
225	return txTime;
226}
227
228typedef enum {
229	WIRELESS_MODE_11a   = 0,
230	WIRELESS_MODE_TURBO = 1,
231	WIRELESS_MODE_11b   = 2,
232	WIRELESS_MODE_11g   = 3,
233	WIRELESS_MODE_108g  = 4,
234
235	WIRELESS_MODE_MAX
236} WIRELESS_MODE;
237
238static WIRELESS_MODE
239ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
240{
241	if (IEEE80211_IS_CHAN_B(chan))
242		return WIRELESS_MODE_11b;
243	if (IEEE80211_IS_CHAN_G(chan))
244		return WIRELESS_MODE_11g;
245	if (IEEE80211_IS_CHAN_108G(chan))
246		return WIRELESS_MODE_108g;
247	if (IEEE80211_IS_CHAN_TURBO(chan))
248		return WIRELESS_MODE_TURBO;
249	return WIRELESS_MODE_11a;
250}
251
252/*
253 * Convert between microseconds and core system clocks.
254 */
255                                     /* 11a Turbo  11b  11g  108g */
256static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
257
258u_int
259ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
260{
261	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
262	u_int clks;
263
264	/* NB: ah_curchan may be null when called attach time */
265	if (c != AH_NULL) {
266		clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
267		if (IEEE80211_IS_CHAN_HT40(c))
268			clks <<= 1;
269		else if (IEEE80211_IS_CHAN_HALF(c))
270			clks >>= 1;
271		else if (IEEE80211_IS_CHAN_QUARTER(c))
272			clks >>= 2;
273	} else
274		clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
275	return clks;
276}
277
278u_int
279ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
280{
281	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
282	u_int usec;
283
284	/* NB: ah_curchan may be null when called attach time */
285	if (c != AH_NULL) {
286		usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
287		if (IEEE80211_IS_CHAN_HT40(c))
288			usec >>= 1;
289		else if (IEEE80211_IS_CHAN_HALF(c))
290			usec <<= 1;
291		else if (IEEE80211_IS_CHAN_QUARTER(c))
292			usec <<= 2;
293	} else
294		usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
295	return usec;
296}
297
298/*
299 * Setup a h/w rate table's reverse lookup table and
300 * fill in ack durations.  This routine is called for
301 * each rate table returned through the ah_getRateTable
302 * method.  The reverse lookup tables are assumed to be
303 * initialized to zero (or at least the first entry).
304 * We use this as a key that indicates whether or not
305 * we've previously setup the reverse lookup table.
306 *
307 * XXX not reentrant, but shouldn't matter
308 */
309void
310ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
311{
312#define	N(a)	(sizeof(a)/sizeof(a[0]))
313	int i;
314
315	if (rt->rateCodeToIndex[0] != 0)	/* already setup */
316		return;
317	for (i = 0; i < N(rt->rateCodeToIndex); i++)
318		rt->rateCodeToIndex[i] = (uint8_t) -1;
319	for (i = 0; i < rt->rateCount; i++) {
320		uint8_t code = rt->info[i].rateCode;
321		uint8_t cix = rt->info[i].controlRate;
322
323		HALASSERT(code < N(rt->rateCodeToIndex));
324		rt->rateCodeToIndex[code] = i;
325		HALASSERT((code | rt->info[i].shortPreamble) <
326		    N(rt->rateCodeToIndex));
327		rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
328		/*
329		 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
330		 *     depends on whether they are marked as basic rates;
331		 *     the static tables are setup with an 11b-compatible
332		 *     2Mb/s rate which will work but is suboptimal
333		 */
334		rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
335			WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
336		rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
337			WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
338	}
339#undef N
340}
341
342HAL_STATUS
343ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
344	uint32_t capability, uint32_t *result)
345{
346	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
347
348	switch (type) {
349	case HAL_CAP_REG_DMN:		/* regulatory domain */
350		*result = AH_PRIVATE(ah)->ah_currentRD;
351		return HAL_OK;
352	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
353	case HAL_CAP_TKIP_MIC:		/* handle TKIP MIC in hardware */
354		return HAL_ENOTSUPP;
355	case HAL_CAP_TKIP_SPLIT:	/* hardware TKIP uses split keys */
356		return HAL_ENOTSUPP;
357	case HAL_CAP_PHYCOUNTERS:	/* hardware PHY error counters */
358		return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
359	case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
360		return HAL_ENOTSUPP;
361	case HAL_CAP_DIVERSITY:		/* hardware supports fast diversity */
362		return HAL_ENOTSUPP;
363	case HAL_CAP_KEYCACHE_SIZE:	/* hardware key cache size */
364		*result =  pCap->halKeyCacheSize;
365		return HAL_OK;
366	case HAL_CAP_NUM_TXQUEUES:	/* number of hardware tx queues */
367		*result = pCap->halTotalQueues;
368		return HAL_OK;
369	case HAL_CAP_VEOL:		/* hardware supports virtual EOL */
370		return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
371	case HAL_CAP_PSPOLL:		/* hardware PS-Poll support works */
372		return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
373	case HAL_CAP_COMPRESSION:
374		return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
375	case HAL_CAP_BURST:
376		return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
377	case HAL_CAP_FASTFRAME:
378		return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
379	case HAL_CAP_DIAG:		/* hardware diagnostic support */
380		*result = AH_PRIVATE(ah)->ah_diagreg;
381		return HAL_OK;
382	case HAL_CAP_TXPOW:		/* global tx power limit  */
383		switch (capability) {
384		case 0:			/* facility is supported */
385			return HAL_OK;
386		case 1:			/* current limit */
387			*result = AH_PRIVATE(ah)->ah_powerLimit;
388			return HAL_OK;
389		case 2:			/* current max tx power */
390			*result = AH_PRIVATE(ah)->ah_maxPowerLevel;
391			return HAL_OK;
392		case 3:			/* scale factor */
393			*result = AH_PRIVATE(ah)->ah_tpScale;
394			return HAL_OK;
395		}
396		return HAL_ENOTSUPP;
397	case HAL_CAP_BSSIDMASK:		/* hardware supports bssid mask */
398		return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
399	case HAL_CAP_MCAST_KEYSRCH:	/* multicast frame keycache search */
400		return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
401	case HAL_CAP_TSF_ADJUST:	/* hardware has beacon tsf adjust */
402		return HAL_ENOTSUPP;
403	case HAL_CAP_RFSILENT:		/* rfsilent support  */
404		switch (capability) {
405		case 0:			/* facility is supported */
406			return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
407		case 1:			/* current setting */
408			return AH_PRIVATE(ah)->ah_rfkillEnabled ?
409				HAL_OK : HAL_ENOTSUPP;
410		case 2:			/* rfsilent config */
411			*result = AH_PRIVATE(ah)->ah_rfsilent;
412			return HAL_OK;
413		}
414		return HAL_ENOTSUPP;
415	case HAL_CAP_11D:
416		return HAL_OK;
417	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
418		return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
419	case HAL_CAP_HT:
420		return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
421	case HAL_CAP_TX_CHAINMASK:	/* mask of TX chains supported */
422		*result = pCap->halTxChainMask;
423		return HAL_OK;
424	case HAL_CAP_RX_CHAINMASK:	/* mask of RX chains supported */
425		*result = pCap->halRxChainMask;
426		return HAL_OK;
427	case HAL_CAP_RXTSTAMP_PREC:	/* rx desc tstamp precision (bits) */
428		*result = pCap->halTstampPrecision;
429		return HAL_OK;
430	default:
431		return HAL_EINVAL;
432	}
433}
434
435HAL_BOOL
436ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
437	uint32_t capability, uint32_t setting, HAL_STATUS *status)
438{
439
440	switch (type) {
441	case HAL_CAP_TXPOW:
442		switch (capability) {
443		case 3:
444			if (setting <= HAL_TP_SCALE_MIN) {
445				AH_PRIVATE(ah)->ah_tpScale = setting;
446				return AH_TRUE;
447			}
448			break;
449		}
450		break;
451	case HAL_CAP_RFSILENT:		/* rfsilent support  */
452		/*
453		 * NB: allow even if halRfSilentSupport is false
454		 *     in case the EEPROM is misprogrammed.
455		 */
456		switch (capability) {
457		case 1:			/* current setting */
458			AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
459			return AH_TRUE;
460		case 2:			/* rfsilent config */
461			/* XXX better done per-chip for validation? */
462			AH_PRIVATE(ah)->ah_rfsilent = setting;
463			return AH_TRUE;
464		}
465		break;
466	case HAL_CAP_REG_DMN:		/* regulatory domain */
467		AH_PRIVATE(ah)->ah_currentRD = setting;
468		return AH_TRUE;
469	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
470		AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
471		return AH_TRUE;
472	default:
473		break;
474	}
475	if (status)
476		*status = HAL_EINVAL;
477	return AH_FALSE;
478}
479
480/*
481 * Common support for getDiagState method.
482 */
483
484static u_int
485ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
486	void *dstbuf, int space)
487{
488	uint32_t *dp = dstbuf;
489	int i;
490
491	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
492		u_int r = regs[i].start;
493		u_int e = regs[i].end;
494		*dp++ = (r<<16) | e;
495		space -= sizeof(uint32_t);
496		do {
497			*dp++ = OS_REG_READ(ah, r);
498			r += sizeof(uint32_t);
499			space -= sizeof(uint32_t);
500		} while (r <= e && space >= sizeof(uint32_t));
501	}
502	return (char *) dp - (char *) dstbuf;
503}
504
505static void
506ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
507{
508	while (space >= sizeof(HAL_REGWRITE)) {
509		OS_REG_WRITE(ah, regs->addr, regs->value);
510		regs++, space -= sizeof(HAL_REGWRITE);
511	}
512}
513
514HAL_BOOL
515ath_hal_getdiagstate(struct ath_hal *ah, int request,
516	const void *args, uint32_t argsize,
517	void **result, uint32_t *resultsize)
518{
519	switch (request) {
520	case HAL_DIAG_REVS:
521		*result = &AH_PRIVATE(ah)->ah_devid;
522		*resultsize = sizeof(HAL_REVS);
523		return AH_TRUE;
524	case HAL_DIAG_REGS:
525		*resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
526		return AH_TRUE;
527	case HAL_DIAG_SETREGS:
528		ath_hal_setregs(ah, args, argsize);
529		*resultsize = 0;
530		return AH_TRUE;
531	case HAL_DIAG_FATALERR:
532		*result = &AH_PRIVATE(ah)->ah_fatalState[0];
533		*resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
534		return AH_TRUE;
535	case HAL_DIAG_EEREAD:
536		if (argsize != sizeof(uint16_t))
537			return AH_FALSE;
538		if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
539			return AH_FALSE;
540		*resultsize = sizeof(uint16_t);
541		return AH_TRUE;
542#ifdef AH_PRIVATE_DIAG
543	case HAL_DIAG_SETKEY: {
544		const HAL_DIAG_KEYVAL *dk;
545
546		if (argsize != sizeof(HAL_DIAG_KEYVAL))
547			return AH_FALSE;
548		dk = (const HAL_DIAG_KEYVAL *)args;
549		return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
550			&dk->dk_keyval, dk->dk_mac, dk->dk_xor);
551	}
552	case HAL_DIAG_RESETKEY:
553		if (argsize != sizeof(uint16_t))
554			return AH_FALSE;
555		return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
556#ifdef AH_SUPPORT_WRITE_EEPROM
557	case HAL_DIAG_EEWRITE: {
558		const HAL_DIAG_EEVAL *ee;
559		if (argsize != sizeof(HAL_DIAG_EEVAL))
560			return AH_FALSE;
561		ee = (const HAL_DIAG_EEVAL *)args;
562		return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
563	}
564#endif /* AH_SUPPORT_WRITE_EEPROM */
565#endif /* AH_PRIVATE_DIAG */
566	case HAL_DIAG_11NCOMPAT:
567		if (argsize == 0) {
568			*resultsize = sizeof(uint32_t);
569			*((uint32_t *)(*result)) =
570				AH_PRIVATE(ah)->ah_11nCompat;
571		} else if (argsize == sizeof(uint32_t)) {
572			AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
573		} else
574			return AH_FALSE;
575		return AH_TRUE;
576	}
577	return AH_FALSE;
578}
579
580/*
581 * Set the properties of the tx queue with the parameters
582 * from qInfo.
583 */
584HAL_BOOL
585ath_hal_setTxQProps(struct ath_hal *ah,
586	HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
587{
588	uint32_t cw;
589
590	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
591		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
592		    "%s: inactive queue\n", __func__);
593		return AH_FALSE;
594	}
595	/* XXX validate parameters */
596	qi->tqi_ver = qInfo->tqi_ver;
597	qi->tqi_subtype = qInfo->tqi_subtype;
598	qi->tqi_qflags = qInfo->tqi_qflags;
599	qi->tqi_priority = qInfo->tqi_priority;
600	if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
601		qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
602	else
603		qi->tqi_aifs = INIT_AIFS;
604	if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
605		cw = AH_MIN(qInfo->tqi_cwmin, 1024);
606		/* make sure that the CWmin is of the form (2^n - 1) */
607		qi->tqi_cwmin = 1;
608		while (qi->tqi_cwmin < cw)
609			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
610	} else
611		qi->tqi_cwmin = qInfo->tqi_cwmin;
612	if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
613		cw = AH_MIN(qInfo->tqi_cwmax, 1024);
614		/* make sure that the CWmax is of the form (2^n - 1) */
615		qi->tqi_cwmax = 1;
616		while (qi->tqi_cwmax < cw)
617			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
618	} else
619		qi->tqi_cwmax = INIT_CWMAX;
620	/* Set retry limit values */
621	if (qInfo->tqi_shretry != 0)
622		qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
623	else
624		qi->tqi_shretry = INIT_SH_RETRY;
625	if (qInfo->tqi_lgretry != 0)
626		qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
627	else
628		qi->tqi_lgretry = INIT_LG_RETRY;
629	qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
630	qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
631	qi->tqi_burstTime = qInfo->tqi_burstTime;
632	qi->tqi_readyTime = qInfo->tqi_readyTime;
633
634	switch (qInfo->tqi_subtype) {
635	case HAL_WME_UPSD:
636		if (qi->tqi_type == HAL_TX_QUEUE_DATA)
637			qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
638		break;
639	default:
640		break;		/* NB: silence compiler */
641	}
642	return AH_TRUE;
643}
644
645HAL_BOOL
646ath_hal_getTxQProps(struct ath_hal *ah,
647	HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
648{
649	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
650		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
651		    "%s: inactive queue\n", __func__);
652		return AH_FALSE;
653	}
654
655	qInfo->tqi_qflags = qi->tqi_qflags;
656	qInfo->tqi_ver = qi->tqi_ver;
657	qInfo->tqi_subtype = qi->tqi_subtype;
658	qInfo->tqi_qflags = qi->tqi_qflags;
659	qInfo->tqi_priority = qi->tqi_priority;
660	qInfo->tqi_aifs = qi->tqi_aifs;
661	qInfo->tqi_cwmin = qi->tqi_cwmin;
662	qInfo->tqi_cwmax = qi->tqi_cwmax;
663	qInfo->tqi_shretry = qi->tqi_shretry;
664	qInfo->tqi_lgretry = qi->tqi_lgretry;
665	qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
666	qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
667	qInfo->tqi_burstTime = qi->tqi_burstTime;
668	qInfo->tqi_readyTime = qi->tqi_readyTime;
669	return AH_TRUE;
670}
671
672                                     /* 11a Turbo  11b  11g  108g */
673static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
674
675/*
676 * Read the current channel noise floor and return.
677 * If nf cal hasn't finished, channel noise floor should be 0
678 * and we return a nominal value based on band and frequency.
679 *
680 * NB: This is a private routine used by per-chip code to
681 *     implement the ah_getChanNoise method.
682 */
683int16_t
684ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
685{
686	HAL_CHANNEL_INTERNAL *ichan;
687
688	ichan = ath_hal_checkchannel(ah, chan);
689	if (ichan == AH_NULL) {
690		HALDEBUG(ah, HAL_DEBUG_NFCAL,
691		    "%s: invalid channel %u/0x%x; no mapping\n",
692		    __func__, chan->ic_freq, chan->ic_flags);
693		return 0;
694	}
695	if (ichan->rawNoiseFloor == 0) {
696		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
697
698		HALASSERT(mode < WIRELESS_MODE_MAX);
699		return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
700	} else
701		return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
702}
703
704/*
705 * Process all valid raw noise floors into the dBm noise floor values.
706 * Though our device has no reference for a dBm noise floor, we perform
707 * a relative minimization of NF's based on the lowest NF found across a
708 * channel scan.
709 */
710void
711ath_hal_process_noisefloor(struct ath_hal *ah)
712{
713	HAL_CHANNEL_INTERNAL *c;
714	int16_t correct2, correct5;
715	int16_t lowest2, lowest5;
716	int i;
717
718	/*
719	 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
720	 * for statistically recorded NF/channel deviation.
721	 */
722	correct2 = lowest2 = 0;
723	correct5 = lowest5 = 0;
724	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
725		WIRELESS_MODE mode;
726		int16_t nf;
727
728		c = &AH_PRIVATE(ah)->ah_channels[i];
729		if (c->rawNoiseFloor >= 0)
730			continue;
731		/* XXX can't identify proper mode */
732		mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
733		nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
734			ath_hal_getNfAdjust(ah, c);
735		if (IS_CHAN_5GHZ(c)) {
736			if (nf < lowest5) {
737				lowest5 = nf;
738				correct5 = NOISE_FLOOR[mode] -
739				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
740			}
741		} else {
742			if (nf < lowest2) {
743				lowest2 = nf;
744				correct2 = NOISE_FLOOR[mode] -
745				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
746			}
747		}
748	}
749
750	/* Correct the channels to reach the expected NF value */
751	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
752		c = &AH_PRIVATE(ah)->ah_channels[i];
753		if (c->rawNoiseFloor >= 0)
754			continue;
755		/* Apply correction factor */
756		c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
757			(IS_CHAN_5GHZ(c) ? correct5 : correct2);
758		HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
759		    c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
760	}
761}
762
763/*
764 * INI support routines.
765 */
766
767int
768ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
769	int col, int regWr)
770{
771	int r;
772
773	for (r = 0; r < ia->rows; r++) {
774		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
775		    HAL_INI_VAL(ia, r, col));
776		DMA_YIELD(regWr);
777	}
778	return regWr;
779}
780
781void
782ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
783{
784	int r;
785
786	for (r = 0; r < ia->rows; r++)
787		data[r] = HAL_INI_VAL(ia, r, col);
788}
789
790int
791ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
792	const uint32_t data[], int regWr)
793{
794	int r;
795
796	for (r = 0; r < ia->rows; r++) {
797		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
798		DMA_YIELD(regWr);
799	}
800	return regWr;
801}
802