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