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$
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24#include "ah_eeprom.h"			/* for 5ghz fast clock flag */
25
26#include "ar5416/ar5416reg.h"		/* NB: includes ar5212reg.h */
27#include "ar9003/ar9300_devid.h"
28
29/* linker set of registered chips */
30OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
31
32/*
33 * Check the set of registered chips to see if any recognize
34 * the device as one they can support.
35 */
36const char*
37ath_hal_probe(uint16_t vendorid, uint16_t devid)
38{
39	struct ath_hal_chip * const *pchip;
40
41	OS_SET_FOREACH(pchip, ah_chips) {
42		const char *name = (*pchip)->probe(vendorid, devid);
43		if (name != AH_NULL)
44			return name;
45	}
46	return AH_NULL;
47}
48
49/*
50 * Attach detects device chip revisions, initializes the hwLayer
51 * function list, reads EEPROM information,
52 * selects reset vectors, and performs a short self test.
53 * Any failures will return an error that should cause a hardware
54 * disable.
55 */
56struct ath_hal*
57ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
58	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
59	HAL_OPS_CONFIG *ah_config,
60	HAL_STATUS *error)
61{
62	struct ath_hal_chip * const *pchip;
63
64	OS_SET_FOREACH(pchip, ah_chips) {
65		struct ath_hal_chip *chip = *pchip;
66		struct ath_hal *ah;
67
68		/* XXX don't have vendorid, assume atheros one works */
69		if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
70			continue;
71		ah = chip->attach(devid, sc, st, sh, eepromdata, ah_config,
72		    error);
73		if (ah != AH_NULL) {
74			/* copy back private state to public area */
75			ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
76			ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
77			ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
78			ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
79			ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
80			ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
81			ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
82			return ah;
83		}
84	}
85	return AH_NULL;
86}
87
88const char *
89ath_hal_mac_name(struct ath_hal *ah)
90{
91	switch (ah->ah_macVersion) {
92	case AR_SREV_VERSION_CRETE:
93	case AR_SREV_VERSION_MAUI_1:
94		return "AR5210";
95	case AR_SREV_VERSION_MAUI_2:
96	case AR_SREV_VERSION_OAHU:
97		return "AR5211";
98	case AR_SREV_VERSION_VENICE:
99		return "AR5212";
100	case AR_SREV_VERSION_GRIFFIN:
101		return "AR2413";
102	case AR_SREV_VERSION_CONDOR:
103		return "AR5424";
104	case AR_SREV_VERSION_EAGLE:
105		return "AR5413";
106	case AR_SREV_VERSION_COBRA:
107		return "AR2415";
108	case AR_SREV_2425:	/* Swan */
109		return "AR2425";
110	case AR_SREV_2417:	/* Nala */
111		return "AR2417";
112	case AR_XSREV_VERSION_OWL_PCI:
113		return "AR5416";
114	case AR_XSREV_VERSION_OWL_PCIE:
115		return "AR5418";
116	case AR_XSREV_VERSION_HOWL:
117		return "AR9130";
118	case AR_XSREV_VERSION_SOWL:
119		return "AR9160";
120	case AR_XSREV_VERSION_MERLIN:
121		if (AH_PRIVATE(ah)->ah_ispcie)
122			return "AR9280";
123		return "AR9220";
124	case AR_XSREV_VERSION_KITE:
125		return "AR9285";
126	case AR_XSREV_VERSION_KIWI:
127		if (AH_PRIVATE(ah)->ah_ispcie)
128			return "AR9287";
129		return "AR9227";
130	case AR_SREV_VERSION_AR9380:
131		if (ah->ah_macRev >= AR_SREV_REVISION_AR9580_10)
132			return "AR9580";
133		return "AR9380";
134	case AR_SREV_VERSION_AR9460:
135		return "AR9460";
136	case AR_SREV_VERSION_AR9330:
137		return "AR9330";
138	case AR_SREV_VERSION_AR9340:
139		return "AR9340";
140	case AR_SREV_VERSION_QCA9550:
141		return "QCA9550";
142	case AR_SREV_VERSION_AR9485:
143		return "AR9485";
144	case AR_SREV_VERSION_QCA9565:
145		return "QCA9565";
146	case AR_SREV_VERSION_QCA9530:
147		return "QCA9530";
148	}
149	return "????";
150}
151
152/*
153 * Return the mask of available modes based on the hardware capabilities.
154 */
155u_int
156ath_hal_getwirelessmodes(struct ath_hal*ah)
157{
158	return ath_hal_getWirelessModes(ah);
159}
160
161/* linker set of registered RF backends */
162OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
163
164/*
165 * Check the set of registered RF backends to see if
166 * any recognize the device as one they can support.
167 */
168struct ath_hal_rf *
169ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
170{
171	struct ath_hal_rf * const *prf;
172
173	OS_SET_FOREACH(prf, ah_rfs) {
174		struct ath_hal_rf *rf = *prf;
175		if (rf->probe(ah))
176			return rf;
177	}
178	*ecode = HAL_ENOTSUPP;
179	return AH_NULL;
180}
181
182const char *
183ath_hal_rf_name(struct ath_hal *ah)
184{
185	switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
186	case 0:			/* 5210 */
187		return "5110";	/* NB: made up */
188	case AR_RAD5111_SREV_MAJOR:
189	case AR_RAD5111_SREV_PROD:
190		return "5111";
191	case AR_RAD2111_SREV_MAJOR:
192		return "2111";
193	case AR_RAD5112_SREV_MAJOR:
194	case AR_RAD5112_SREV_2_0:
195	case AR_RAD5112_SREV_2_1:
196		return "5112";
197	case AR_RAD2112_SREV_MAJOR:
198	case AR_RAD2112_SREV_2_0:
199	case AR_RAD2112_SREV_2_1:
200		return "2112";
201	case AR_RAD2413_SREV_MAJOR:
202		return "2413";
203	case AR_RAD5413_SREV_MAJOR:
204		return "5413";
205	case AR_RAD2316_SREV_MAJOR:
206		return "2316";
207	case AR_RAD2317_SREV_MAJOR:
208		return "2317";
209	case AR_RAD5424_SREV_MAJOR:
210		return "5424";
211
212	case AR_RAD5133_SREV_MAJOR:
213		return "5133";
214	case AR_RAD2133_SREV_MAJOR:
215		return "2133";
216	case AR_RAD5122_SREV_MAJOR:
217		return "5122";
218	case AR_RAD2122_SREV_MAJOR:
219		return "2122";
220	}
221	return "????";
222}
223
224/*
225 * Poll the register looking for a specific value.
226 */
227HAL_BOOL
228ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
229{
230#define	AH_TIMEOUT	1000
231	return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
232#undef AH_TIMEOUT
233}
234
235HAL_BOOL
236ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
237{
238	int i;
239
240	for (i = 0; i < timeout; i++) {
241		if ((OS_REG_READ(ah, reg) & mask) == val)
242			return AH_TRUE;
243		OS_DELAY(10);
244	}
245	HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
246	    "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
247	    __func__, reg, OS_REG_READ(ah, reg), mask, val);
248	return AH_FALSE;
249}
250
251/*
252 * Reverse the bits starting at the low bit for a value of
253 * bit_count in size
254 */
255uint32_t
256ath_hal_reverseBits(uint32_t val, uint32_t n)
257{
258	uint32_t retval;
259	int i;
260
261	for (i = 0, retval = 0; i < n; i++) {
262		retval = (retval << 1) | (val & 1);
263		val >>= 1;
264	}
265	return retval;
266}
267
268/* 802.11n related timing definitions */
269
270#define	OFDM_PLCP_BITS	22
271#define	HT_L_STF	8
272#define	HT_L_LTF	8
273#define	HT_L_SIG	4
274#define	HT_SIG		8
275#define	HT_STF		4
276#define	HT_LTF(n)	((n) * 4)
277
278#define	HT_RC_2_MCS(_rc)	((_rc) & 0xf)
279#define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
280#define	IS_HT_RATE(_rc)		( (_rc) & IEEE80211_RATE_MCS)
281
282/*
283 * Calculate the duration of a packet whether it is 11n or legacy.
284 */
285uint32_t
286ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
287    uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
288{
289	uint8_t rc;
290	int numStreams;
291
292	rc = rates->info[rateix].rateCode;
293
294	/* Legacy rate? Return the old way */
295	if (! IS_HT_RATE(rc))
296		return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
297
298	/* 11n frame - extract out the number of spatial streams */
299	numStreams = HT_RC_2_STREAMS(rc);
300	KASSERT(numStreams > 0 && numStreams <= 4,
301	    ("number of spatial streams needs to be 1..3: MCS rate 0x%x!",
302	    rateix));
303
304	return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
305}
306
307static const uint16_t ht20_bps[32] = {
308    26, 52, 78, 104, 156, 208, 234, 260,
309    52, 104, 156, 208, 312, 416, 468, 520,
310    78, 156, 234, 312, 468, 624, 702, 780,
311    104, 208, 312, 416, 624, 832, 936, 1040
312};
313static const uint16_t ht40_bps[32] = {
314    54, 108, 162, 216, 324, 432, 486, 540,
315    108, 216, 324, 432, 648, 864, 972, 1080,
316    162, 324, 486, 648, 972, 1296, 1458, 1620,
317    216, 432, 648, 864, 1296, 1728, 1944, 2160
318};
319
320/*
321 * Calculate the transmit duration of an 11n frame.
322 */
323uint32_t
324ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams,
325    HAL_BOOL isht40, HAL_BOOL isShortGI)
326{
327	uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
328
329	KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
330	KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate));
331
332	if (isht40)
333		bitsPerSymbol = ht40_bps[rate & 0x1f];
334	else
335		bitsPerSymbol = ht20_bps[rate & 0x1f];
336	numBits = OFDM_PLCP_BITS + (frameLen << 3);
337	numSymbols = howmany(numBits, bitsPerSymbol);
338	if (isShortGI)
339		txTime = ((numSymbols * 18) + 4) / 5;   /* 3.6us */
340	else
341		txTime = numSymbols * 4;                /* 4us */
342	return txTime + HT_L_STF + HT_L_LTF +
343	    HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
344}
345
346/*
347 * Compute the time to transmit a frame of length frameLen bytes
348 * using the specified rate, phy, and short preamble setting.
349 */
350uint16_t
351ath_hal_computetxtime(struct ath_hal *ah,
352	const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
353	HAL_BOOL shortPreamble)
354{
355	uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
356	uint32_t kbps;
357
358	/* Warn if this function is called for 11n rates; it should not be! */
359	if (IS_HT_RATE(rates->info[rateix].rateCode))
360		ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
361		    __func__, rateix, rates->info[rateix].rateCode);
362
363	kbps = rates->info[rateix].rateKbps;
364	/*
365	 * index can be invalid during dynamic Turbo transitions.
366	 * XXX
367	 */
368	if (kbps == 0)
369		return 0;
370	switch (rates->info[rateix].phy) {
371	case IEEE80211_T_CCK:
372		phyTime		= CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
373		if (shortPreamble && rates->info[rateix].shortPreamble)
374			phyTime >>= 1;
375		numBits		= frameLen << 3;
376		txTime		= CCK_SIFS_TIME + phyTime
377				+ ((numBits * 1000)/kbps);
378		break;
379	case IEEE80211_T_OFDM:
380		bitsPerSymbol	= (kbps * OFDM_SYMBOL_TIME) / 1000;
381		HALASSERT(bitsPerSymbol != 0);
382
383		numBits		= OFDM_PLCP_BITS + (frameLen << 3);
384		numSymbols	= howmany(numBits, bitsPerSymbol);
385		txTime		= OFDM_SIFS_TIME
386				+ OFDM_PREAMBLE_TIME
387				+ (numSymbols * OFDM_SYMBOL_TIME);
388		break;
389	case IEEE80211_T_OFDM_HALF:
390		bitsPerSymbol	= (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
391		HALASSERT(bitsPerSymbol != 0);
392
393		numBits		= OFDM_HALF_PLCP_BITS + (frameLen << 3);
394		numSymbols	= howmany(numBits, bitsPerSymbol);
395		txTime		= OFDM_HALF_SIFS_TIME
396				+ OFDM_HALF_PREAMBLE_TIME
397				+ (numSymbols * OFDM_HALF_SYMBOL_TIME);
398		break;
399	case IEEE80211_T_OFDM_QUARTER:
400		bitsPerSymbol	= (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
401		HALASSERT(bitsPerSymbol != 0);
402
403		numBits		= OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
404		numSymbols	= howmany(numBits, bitsPerSymbol);
405		txTime		= OFDM_QUARTER_SIFS_TIME
406				+ OFDM_QUARTER_PREAMBLE_TIME
407				+ (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
408		break;
409	case IEEE80211_T_TURBO:
410		bitsPerSymbol	= (kbps * TURBO_SYMBOL_TIME) / 1000;
411		HALASSERT(bitsPerSymbol != 0);
412
413		numBits		= TURBO_PLCP_BITS + (frameLen << 3);
414		numSymbols	= howmany(numBits, bitsPerSymbol);
415		txTime		= TURBO_SIFS_TIME
416				+ TURBO_PREAMBLE_TIME
417				+ (numSymbols * TURBO_SYMBOL_TIME);
418		break;
419	default:
420		HALDEBUG(ah, HAL_DEBUG_PHYIO,
421		    "%s: unknown phy %u (rate ix %u)\n",
422		    __func__, rates->info[rateix].phy, rateix);
423		txTime = 0;
424		break;
425	}
426	return txTime;
427}
428
429int
430ath_hal_get_curmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
431{
432	/*
433	 * Pick a default mode at bootup. A channel change is inevitable.
434	 */
435	if (!chan)
436		return HAL_MODE_11NG_HT20;
437
438	if (IEEE80211_IS_CHAN_TURBO(chan))
439		return HAL_MODE_TURBO;
440
441	/* check for NA_HT before plain A, since IS_CHAN_A includes NA_HT */
442	if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
443		return HAL_MODE_11NA_HT20;
444	if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
445		return HAL_MODE_11NA_HT40PLUS;
446	if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
447		return HAL_MODE_11NA_HT40MINUS;
448	if (IEEE80211_IS_CHAN_A(chan))
449		return HAL_MODE_11A;
450
451	/* check for NG_HT before plain G, since IS_CHAN_G includes NG_HT */
452	if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
453		return HAL_MODE_11NG_HT20;
454	if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
455		return HAL_MODE_11NG_HT40PLUS;
456	if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
457		return HAL_MODE_11NG_HT40MINUS;
458
459	/*
460	 * XXX For FreeBSD, will this work correctly given the DYN
461	 * chan mode (OFDM+CCK dynamic) ? We have pure-G versions DYN-BG..
462	 */
463	if (IEEE80211_IS_CHAN_G(chan))
464		return HAL_MODE_11G;
465	if (IEEE80211_IS_CHAN_B(chan))
466		return HAL_MODE_11B;
467
468	HALASSERT(0);
469	return HAL_MODE_11NG_HT20;
470}
471
472
473typedef enum {
474	WIRELESS_MODE_11a   = 0,
475	WIRELESS_MODE_TURBO = 1,
476	WIRELESS_MODE_11b   = 2,
477	WIRELESS_MODE_11g   = 3,
478	WIRELESS_MODE_108g  = 4,
479
480	WIRELESS_MODE_MAX
481} WIRELESS_MODE;
482
483static WIRELESS_MODE
484ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
485{
486	if (IEEE80211_IS_CHAN_B(chan))
487		return WIRELESS_MODE_11b;
488	if (IEEE80211_IS_CHAN_G(chan))
489		return WIRELESS_MODE_11g;
490	if (IEEE80211_IS_CHAN_108G(chan))
491		return WIRELESS_MODE_108g;
492	if (IEEE80211_IS_CHAN_TURBO(chan))
493		return WIRELESS_MODE_TURBO;
494	return WIRELESS_MODE_11a;
495}
496
497/*
498 * Convert between microseconds and core system clocks.
499 */
500                                     /* 11a Turbo  11b  11g  108g */
501static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
502
503#define	CLOCK_FAST_RATE_5GHZ_OFDM	44
504
505u_int
506ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
507{
508	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
509	u_int clks;
510
511	/* NB: ah_curchan may be null when called attach time */
512	/* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
513	if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
514		clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
515		if (IEEE80211_IS_CHAN_HT40(c))
516			clks <<= 1;
517	} else if (c != AH_NULL) {
518		clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
519		if (IEEE80211_IS_CHAN_HT40(c))
520			clks <<= 1;
521	} else
522		clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
523
524	/* Compensate for half/quarter rate */
525	if (c != AH_NULL && IEEE80211_IS_CHAN_HALF(c))
526		clks = clks / 2;
527	else if (c != AH_NULL && IEEE80211_IS_CHAN_QUARTER(c))
528		clks = clks / 4;
529
530	return clks;
531}
532
533u_int
534ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
535{
536	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
537	u_int usec;
538
539	/* NB: ah_curchan may be null when called attach time */
540	/* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
541	if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
542		usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
543		if (IEEE80211_IS_CHAN_HT40(c))
544			usec >>= 1;
545	} else if (c != AH_NULL) {
546		usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
547		if (IEEE80211_IS_CHAN_HT40(c))
548			usec >>= 1;
549	} else
550		usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
551	return usec;
552}
553
554/*
555 * Setup a h/w rate table's reverse lookup table and
556 * fill in ack durations.  This routine is called for
557 * each rate table returned through the ah_getRateTable
558 * method.  The reverse lookup tables are assumed to be
559 * initialized to zero (or at least the first entry).
560 * We use this as a key that indicates whether or not
561 * we've previously setup the reverse lookup table.
562 *
563 * XXX not reentrant, but shouldn't matter
564 */
565void
566ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
567{
568#define	N(a)	(sizeof(a)/sizeof(a[0]))
569	int i;
570
571	if (rt->rateCodeToIndex[0] != 0)	/* already setup */
572		return;
573	for (i = 0; i < N(rt->rateCodeToIndex); i++)
574		rt->rateCodeToIndex[i] = (uint8_t) -1;
575	for (i = 0; i < rt->rateCount; i++) {
576		uint8_t code = rt->info[i].rateCode;
577		uint8_t cix = rt->info[i].controlRate;
578
579		HALASSERT(code < N(rt->rateCodeToIndex));
580		rt->rateCodeToIndex[code] = i;
581		HALASSERT((code | rt->info[i].shortPreamble) <
582		    N(rt->rateCodeToIndex));
583		rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
584		/*
585		 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
586		 *     depends on whether they are marked as basic rates;
587		 *     the static tables are setup with an 11b-compatible
588		 *     2Mb/s rate which will work but is suboptimal
589		 */
590		rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
591			WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
592		rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
593			WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
594	}
595#undef N
596}
597
598HAL_STATUS
599ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
600	uint32_t capability, uint32_t *result)
601{
602	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
603
604	switch (type) {
605	case HAL_CAP_REG_DMN:		/* regulatory domain */
606		*result = AH_PRIVATE(ah)->ah_currentRD;
607		return HAL_OK;
608	case HAL_CAP_DFS_DMN:		/* DFS Domain */
609		*result = AH_PRIVATE(ah)->ah_dfsDomain;
610		return HAL_OK;
611	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
612	case HAL_CAP_TKIP_MIC:		/* handle TKIP MIC in hardware */
613		return HAL_ENOTSUPP;
614	case HAL_CAP_TKIP_SPLIT:	/* hardware TKIP uses split keys */
615		return HAL_ENOTSUPP;
616	case HAL_CAP_PHYCOUNTERS:	/* hardware PHY error counters */
617		return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
618	case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
619		return HAL_ENOTSUPP;
620	case HAL_CAP_DIVERSITY:		/* hardware supports fast diversity */
621		return HAL_ENOTSUPP;
622	case HAL_CAP_KEYCACHE_SIZE:	/* hardware key cache size */
623		*result =  pCap->halKeyCacheSize;
624		return HAL_OK;
625	case HAL_CAP_NUM_TXQUEUES:	/* number of hardware tx queues */
626		*result = pCap->halTotalQueues;
627		return HAL_OK;
628	case HAL_CAP_VEOL:		/* hardware supports virtual EOL */
629		return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
630	case HAL_CAP_PSPOLL:		/* hardware PS-Poll support works */
631		return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
632	case HAL_CAP_COMPRESSION:
633		return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
634	case HAL_CAP_BURST:
635		return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
636	case HAL_CAP_FASTFRAME:
637		return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
638	case HAL_CAP_DIAG:		/* hardware diagnostic support */
639		*result = AH_PRIVATE(ah)->ah_diagreg;
640		return HAL_OK;
641	case HAL_CAP_TXPOW:		/* global tx power limit  */
642		switch (capability) {
643		case 0:			/* facility is supported */
644			return HAL_OK;
645		case 1:			/* current limit */
646			*result = AH_PRIVATE(ah)->ah_powerLimit;
647			return HAL_OK;
648		case 2:			/* current max tx power */
649			*result = AH_PRIVATE(ah)->ah_maxPowerLevel;
650			return HAL_OK;
651		case 3:			/* scale factor */
652			*result = AH_PRIVATE(ah)->ah_tpScale;
653			return HAL_OK;
654		}
655		return HAL_ENOTSUPP;
656	case HAL_CAP_BSSIDMASK:		/* hardware supports bssid mask */
657		return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
658	case HAL_CAP_MCAST_KEYSRCH:	/* multicast frame keycache search */
659		return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
660	case HAL_CAP_TSF_ADJUST:	/* hardware has beacon tsf adjust */
661		return HAL_ENOTSUPP;
662	case HAL_CAP_RFSILENT:		/* rfsilent support  */
663		switch (capability) {
664		case 0:			/* facility is supported */
665			return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
666		case 1:			/* current setting */
667			return AH_PRIVATE(ah)->ah_rfkillEnabled ?
668				HAL_OK : HAL_ENOTSUPP;
669		case 2:			/* rfsilent config */
670			*result = AH_PRIVATE(ah)->ah_rfsilent;
671			return HAL_OK;
672		}
673		return HAL_ENOTSUPP;
674	case HAL_CAP_11D:
675		return HAL_OK;
676
677	case HAL_CAP_HT:
678		return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
679	case HAL_CAP_GTXTO:
680		return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
681	case HAL_CAP_FAST_CC:
682		return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
683	case HAL_CAP_TX_CHAINMASK:	/* mask of TX chains supported */
684		*result = pCap->halTxChainMask;
685		return HAL_OK;
686	case HAL_CAP_RX_CHAINMASK:	/* mask of RX chains supported */
687		*result = pCap->halRxChainMask;
688		return HAL_OK;
689	case HAL_CAP_NUM_GPIO_PINS:
690		*result = pCap->halNumGpioPins;
691		return HAL_OK;
692	case HAL_CAP_CST:
693		return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
694	case HAL_CAP_RTS_AGGR_LIMIT:
695		*result = pCap->halRtsAggrLimit;
696		return HAL_OK;
697	case HAL_CAP_4ADDR_AGGR:
698		return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
699	case HAL_CAP_EXT_CHAN_DFS:
700		return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
701	case HAL_CAP_RX_STBC:
702		return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
703	case HAL_CAP_TX_STBC:
704		return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
705	case HAL_CAP_COMBINED_RADAR_RSSI:
706		return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
707	case HAL_CAP_AUTO_SLEEP:
708		return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
709	case HAL_CAP_MBSSID_AGGR_SUPPORT:
710		return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
711	case HAL_CAP_SPLIT_4KB_TRANS:	/* hardware handles descriptors straddling 4k page boundary */
712		return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
713	case HAL_CAP_REG_FLAG:
714		*result = AH_PRIVATE(ah)->ah_currentRDext;
715		return HAL_OK;
716	case HAL_CAP_ENHANCED_DMA_SUPPORT:
717		return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP;
718	case HAL_CAP_NUM_TXMAPS:
719		*result = pCap->halNumTxMaps;
720		return HAL_OK;
721	case HAL_CAP_TXDESCLEN:
722		*result = pCap->halTxDescLen;
723		return HAL_OK;
724	case HAL_CAP_TXSTATUSLEN:
725		*result = pCap->halTxStatusLen;
726		return HAL_OK;
727	case HAL_CAP_RXSTATUSLEN:
728		*result = pCap->halRxStatusLen;
729		return HAL_OK;
730	case HAL_CAP_RXFIFODEPTH:
731		switch (capability) {
732		case HAL_RX_QUEUE_HP:
733			*result = pCap->halRxHpFifoDepth;
734			return HAL_OK;
735		case HAL_RX_QUEUE_LP:
736			*result = pCap->halRxLpFifoDepth;
737			return HAL_OK;
738		default:
739			return HAL_ENOTSUPP;
740	}
741	case HAL_CAP_RXBUFSIZE:
742	case HAL_CAP_NUM_MR_RETRIES:
743		*result = pCap->halNumMRRetries;
744		return HAL_OK;
745	case HAL_CAP_BT_COEX:
746		return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
747	case HAL_CAP_SPECTRAL_SCAN:
748		return pCap->halSpectralScanSupport ? HAL_OK : HAL_ENOTSUPP;
749	case HAL_CAP_HT20_SGI:
750		return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
751	case HAL_CAP_RXTSTAMP_PREC:	/* rx desc tstamp precision (bits) */
752		*result = pCap->halTstampPrecision;
753		return HAL_OK;
754	case HAL_CAP_ANT_DIV_COMB:	/* AR9285/AR9485 LNA diversity */
755		return pCap->halAntDivCombSupport ? HAL_OK  : HAL_ENOTSUPP;
756
757	case HAL_CAP_ENHANCED_DFS_SUPPORT:
758		return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
759
760	/* FreeBSD-specific entries for now */
761	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
762		return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
763	case HAL_CAP_INTRMASK:		/* mask of supported interrupts */
764		*result = pCap->halIntrMask;
765		return HAL_OK;
766	case HAL_CAP_BSSIDMATCH:	/* hardware has disable bssid match */
767		return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
768	case HAL_CAP_STREAMS:		/* number of 11n spatial streams */
769		switch (capability) {
770		case 0:			/* TX */
771			*result = pCap->halTxStreams;
772			return HAL_OK;
773		case 1:			/* RX */
774			*result = pCap->halRxStreams;
775			return HAL_OK;
776		default:
777			return HAL_ENOTSUPP;
778		}
779	case HAL_CAP_RXDESC_SELFLINK:	/* hardware supports self-linked final RX descriptors correctly */
780		return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
781	case HAL_CAP_LONG_RXDESC_TSF:		/* 32 bit TSF in RX descriptor? */
782		return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP;
783	case HAL_CAP_BB_READ_WAR:		/* Baseband read WAR */
784		return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP;
785	case HAL_CAP_SERIALISE_WAR:		/* PCI register serialisation */
786		return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP;
787	case HAL_CAP_MFP:			/* Management frame protection setting */
788		*result = pCap->halMfpSupport;
789		return HAL_OK;
790	case HAL_CAP_RX_LNA_MIXING:	/* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */
791		return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP;
792	case HAL_CAP_DO_MYBEACON:	/* Hardware supports filtering my-beacons */
793		return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP;
794	default:
795		return HAL_EINVAL;
796	}
797}
798
799HAL_BOOL
800ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
801	uint32_t capability, uint32_t setting, HAL_STATUS *status)
802{
803
804	switch (type) {
805	case HAL_CAP_TXPOW:
806		switch (capability) {
807		case 3:
808			if (setting <= HAL_TP_SCALE_MIN) {
809				AH_PRIVATE(ah)->ah_tpScale = setting;
810				return AH_TRUE;
811			}
812			break;
813		}
814		break;
815	case HAL_CAP_RFSILENT:		/* rfsilent support  */
816		/*
817		 * NB: allow even if halRfSilentSupport is false
818		 *     in case the EEPROM is misprogrammed.
819		 */
820		switch (capability) {
821		case 1:			/* current setting */
822			AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
823			return AH_TRUE;
824		case 2:			/* rfsilent config */
825			/* XXX better done per-chip for validation? */
826			AH_PRIVATE(ah)->ah_rfsilent = setting;
827			return AH_TRUE;
828		}
829		break;
830	case HAL_CAP_REG_DMN:		/* regulatory domain */
831		AH_PRIVATE(ah)->ah_currentRD = setting;
832		return AH_TRUE;
833	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
834		AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
835		return AH_TRUE;
836	default:
837		break;
838	}
839	if (status)
840		*status = HAL_EINVAL;
841	return AH_FALSE;
842}
843
844/*
845 * Common support for getDiagState method.
846 */
847
848static u_int
849ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
850	void *dstbuf, int space)
851{
852	uint32_t *dp = dstbuf;
853	int i;
854
855	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
856		uint32_t r = regs[i].start;
857		uint32_t e = regs[i].end;
858		*dp++ = r;
859		*dp++ = e;
860		space -= 2*sizeof(uint32_t);
861		do {
862			*dp++ = OS_REG_READ(ah, r);
863			r += sizeof(uint32_t);
864			space -= sizeof(uint32_t);
865		} while (r <= e && space >= sizeof(uint32_t));
866	}
867	return (char *) dp - (char *) dstbuf;
868}
869
870static void
871ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
872{
873	while (space >= sizeof(HAL_REGWRITE)) {
874		OS_REG_WRITE(ah, regs->addr, regs->value);
875		regs++, space -= sizeof(HAL_REGWRITE);
876	}
877}
878
879HAL_BOOL
880ath_hal_getdiagstate(struct ath_hal *ah, int request,
881	const void *args, uint32_t argsize,
882	void **result, uint32_t *resultsize)
883{
884
885	switch (request) {
886	case HAL_DIAG_REVS:
887		*result = &AH_PRIVATE(ah)->ah_devid;
888		*resultsize = sizeof(HAL_REVS);
889		return AH_TRUE;
890	case HAL_DIAG_REGS:
891		*resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
892		return AH_TRUE;
893	case HAL_DIAG_SETREGS:
894		ath_hal_setregs(ah, args, argsize);
895		*resultsize = 0;
896		return AH_TRUE;
897	case HAL_DIAG_FATALERR:
898		*result = &AH_PRIVATE(ah)->ah_fatalState[0];
899		*resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
900		return AH_TRUE;
901	case HAL_DIAG_EEREAD:
902		if (argsize != sizeof(uint16_t))
903			return AH_FALSE;
904		if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
905			return AH_FALSE;
906		*resultsize = sizeof(uint16_t);
907		return AH_TRUE;
908#ifdef AH_PRIVATE_DIAG
909	case HAL_DIAG_SETKEY: {
910		const HAL_DIAG_KEYVAL *dk;
911
912		if (argsize != sizeof(HAL_DIAG_KEYVAL))
913			return AH_FALSE;
914		dk = (const HAL_DIAG_KEYVAL *)args;
915		return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
916			&dk->dk_keyval, dk->dk_mac, dk->dk_xor);
917	}
918	case HAL_DIAG_RESETKEY:
919		if (argsize != sizeof(uint16_t))
920			return AH_FALSE;
921		return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
922#ifdef AH_SUPPORT_WRITE_EEPROM
923	case HAL_DIAG_EEWRITE: {
924		const HAL_DIAG_EEVAL *ee;
925		if (argsize != sizeof(HAL_DIAG_EEVAL))
926			return AH_FALSE;
927		ee = (const HAL_DIAG_EEVAL *)args;
928		return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
929	}
930#endif /* AH_SUPPORT_WRITE_EEPROM */
931#endif /* AH_PRIVATE_DIAG */
932	case HAL_DIAG_11NCOMPAT:
933		if (argsize == 0) {
934			*resultsize = sizeof(uint32_t);
935			*((uint32_t *)(*result)) =
936				AH_PRIVATE(ah)->ah_11nCompat;
937		} else if (argsize == sizeof(uint32_t)) {
938			AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
939		} else
940			return AH_FALSE;
941		return AH_TRUE;
942	case HAL_DIAG_CHANSURVEY:
943		*result = &AH_PRIVATE(ah)->ah_chansurvey;
944		*resultsize = sizeof(HAL_CHANNEL_SURVEY);
945		return AH_TRUE;
946	}
947	return AH_FALSE;
948}
949
950/*
951 * Set the properties of the tx queue with the parameters
952 * from qInfo.
953 */
954HAL_BOOL
955ath_hal_setTxQProps(struct ath_hal *ah,
956	HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
957{
958	uint32_t cw;
959
960	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
961		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
962		    "%s: inactive queue\n", __func__);
963		return AH_FALSE;
964	}
965	/* XXX validate parameters */
966	qi->tqi_ver = qInfo->tqi_ver;
967	qi->tqi_subtype = qInfo->tqi_subtype;
968	qi->tqi_qflags = qInfo->tqi_qflags;
969	qi->tqi_priority = qInfo->tqi_priority;
970	if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
971		qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
972	else
973		qi->tqi_aifs = INIT_AIFS;
974	if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
975		cw = AH_MIN(qInfo->tqi_cwmin, 1024);
976		/* make sure that the CWmin is of the form (2^n - 1) */
977		qi->tqi_cwmin = 1;
978		while (qi->tqi_cwmin < cw)
979			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
980	} else
981		qi->tqi_cwmin = qInfo->tqi_cwmin;
982	if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
983		cw = AH_MIN(qInfo->tqi_cwmax, 1024);
984		/* make sure that the CWmax is of the form (2^n - 1) */
985		qi->tqi_cwmax = 1;
986		while (qi->tqi_cwmax < cw)
987			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
988	} else
989		qi->tqi_cwmax = INIT_CWMAX;
990	/* Set retry limit values */
991	if (qInfo->tqi_shretry != 0)
992		qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
993	else
994		qi->tqi_shretry = INIT_SH_RETRY;
995	if (qInfo->tqi_lgretry != 0)
996		qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
997	else
998		qi->tqi_lgretry = INIT_LG_RETRY;
999	qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
1000	qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
1001	qi->tqi_burstTime = qInfo->tqi_burstTime;
1002	qi->tqi_readyTime = qInfo->tqi_readyTime;
1003
1004	switch (qInfo->tqi_subtype) {
1005	case HAL_WME_UPSD:
1006		if (qi->tqi_type == HAL_TX_QUEUE_DATA)
1007			qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
1008		break;
1009	default:
1010		break;		/* NB: silence compiler */
1011	}
1012	return AH_TRUE;
1013}
1014
1015HAL_BOOL
1016ath_hal_getTxQProps(struct ath_hal *ah,
1017	HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
1018{
1019	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
1020		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
1021		    "%s: inactive queue\n", __func__);
1022		return AH_FALSE;
1023	}
1024
1025	qInfo->tqi_qflags = qi->tqi_qflags;
1026	qInfo->tqi_ver = qi->tqi_ver;
1027	qInfo->tqi_subtype = qi->tqi_subtype;
1028	qInfo->tqi_qflags = qi->tqi_qflags;
1029	qInfo->tqi_priority = qi->tqi_priority;
1030	qInfo->tqi_aifs = qi->tqi_aifs;
1031	qInfo->tqi_cwmin = qi->tqi_cwmin;
1032	qInfo->tqi_cwmax = qi->tqi_cwmax;
1033	qInfo->tqi_shretry = qi->tqi_shretry;
1034	qInfo->tqi_lgretry = qi->tqi_lgretry;
1035	qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
1036	qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
1037	qInfo->tqi_burstTime = qi->tqi_burstTime;
1038	qInfo->tqi_readyTime = qi->tqi_readyTime;
1039	return AH_TRUE;
1040}
1041
1042                                     /* 11a Turbo  11b  11g  108g */
1043static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
1044
1045/*
1046 * Read the current channel noise floor and return.
1047 * If nf cal hasn't finished, channel noise floor should be 0
1048 * and we return a nominal value based on band and frequency.
1049 *
1050 * NB: This is a private routine used by per-chip code to
1051 *     implement the ah_getChanNoise method.
1052 */
1053int16_t
1054ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
1055{
1056	HAL_CHANNEL_INTERNAL *ichan;
1057
1058	ichan = ath_hal_checkchannel(ah, chan);
1059	if (ichan == AH_NULL) {
1060		HALDEBUG(ah, HAL_DEBUG_NFCAL,
1061		    "%s: invalid channel %u/0x%x; no mapping\n",
1062		    __func__, chan->ic_freq, chan->ic_flags);
1063		return 0;
1064	}
1065	if (ichan->rawNoiseFloor == 0) {
1066		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1067
1068		HALASSERT(mode < WIRELESS_MODE_MAX);
1069		return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
1070	} else
1071		return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
1072}
1073
1074/*
1075 * Fetch the current setup of ctl/ext noise floor values.
1076 *
1077 * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
1078 * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
1079 *
1080 * The caller must supply ctl/ext NF arrays which are at least
1081 * AH_MAX_CHAINS entries long.
1082 */
1083int
1084ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
1085    const struct ieee80211_channel *chan, int16_t *nf_ctl,
1086    int16_t *nf_ext)
1087{
1088#ifdef	AH_SUPPORT_AR5416
1089	HAL_CHANNEL_INTERNAL *ichan;
1090	int i;
1091
1092	ichan = ath_hal_checkchannel(ah, chan);
1093	if (ichan == AH_NULL) {
1094		HALDEBUG(ah, HAL_DEBUG_NFCAL,
1095		    "%s: invalid channel %u/0x%x; no mapping\n",
1096		    __func__, chan->ic_freq, chan->ic_flags);
1097		for (i = 0; i < AH_MAX_CHAINS; i++) {
1098			nf_ctl[i] = nf_ext[i] = 0;
1099		}
1100		return 0;
1101	}
1102
1103	/* Return 0 if there's no valid MIMO values (yet) */
1104	if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
1105		for (i = 0; i < AH_MAX_CHAINS; i++) {
1106			nf_ctl[i] = nf_ext[i] = 0;
1107		}
1108		return 0;
1109	}
1110	if (ichan->rawNoiseFloor == 0) {
1111		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1112		HALASSERT(mode < WIRELESS_MODE_MAX);
1113		/*
1114		 * See the comment below - this could cause issues for
1115		 * stations which have a very low RSSI, below the
1116		 * 'normalised' NF values in NOISE_FLOOR[].
1117		 */
1118		for (i = 0; i < AH_MAX_CHAINS; i++) {
1119			nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
1120			    ath_hal_getNfAdjust(ah, ichan);
1121		}
1122		return 1;
1123	} else {
1124		/*
1125		 * The value returned here from a MIMO radio is presumed to be
1126		 * "good enough" as a NF calculation. As RSSI values are calculated
1127		 * against this, an adjusted NF may be higher than the RSSI value
1128		 * returned from a vary weak station, resulting in an obscenely
1129		 * high signal strength calculation being returned.
1130		 *
1131		 * This should be re-evaluated at a later date, along with any
1132		 * signal strength calculations which are made. Quite likely the
1133		 * RSSI values will need to be adjusted to ensure the calculations
1134		 * don't "wrap" when RSSI is less than the "adjusted" NF value.
1135		 * ("Adjust" here is via ichan->noiseFloorAdjust.)
1136		 */
1137		for (i = 0; i < AH_MAX_CHAINS; i++) {
1138			nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
1139			nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
1140		}
1141		return 1;
1142	}
1143#else
1144	return 0;
1145#endif	/* AH_SUPPORT_AR5416 */
1146}
1147
1148/*
1149 * Process all valid raw noise floors into the dBm noise floor values.
1150 * Though our device has no reference for a dBm noise floor, we perform
1151 * a relative minimization of NF's based on the lowest NF found across a
1152 * channel scan.
1153 */
1154void
1155ath_hal_process_noisefloor(struct ath_hal *ah)
1156{
1157	HAL_CHANNEL_INTERNAL *c;
1158	int16_t correct2, correct5;
1159	int16_t lowest2, lowest5;
1160	int i;
1161
1162	/*
1163	 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
1164	 * for statistically recorded NF/channel deviation.
1165	 */
1166	correct2 = lowest2 = 0;
1167	correct5 = lowest5 = 0;
1168	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1169		WIRELESS_MODE mode;
1170		int16_t nf;
1171
1172		c = &AH_PRIVATE(ah)->ah_channels[i];
1173		if (c->rawNoiseFloor >= 0)
1174			continue;
1175		/* XXX can't identify proper mode */
1176		mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
1177		nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
1178			ath_hal_getNfAdjust(ah, c);
1179		if (IS_CHAN_5GHZ(c)) {
1180			if (nf < lowest5) {
1181				lowest5 = nf;
1182				correct5 = NOISE_FLOOR[mode] -
1183				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1184			}
1185		} else {
1186			if (nf < lowest2) {
1187				lowest2 = nf;
1188				correct2 = NOISE_FLOOR[mode] -
1189				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1190			}
1191		}
1192	}
1193
1194	/* Correct the channels to reach the expected NF value */
1195	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1196		c = &AH_PRIVATE(ah)->ah_channels[i];
1197		if (c->rawNoiseFloor >= 0)
1198			continue;
1199		/* Apply correction factor */
1200		c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
1201			(IS_CHAN_5GHZ(c) ? correct5 : correct2);
1202		HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
1203		    c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
1204	}
1205}
1206
1207/*
1208 * INI support routines.
1209 */
1210
1211int
1212ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1213	int col, int regWr)
1214{
1215	int r;
1216
1217	HALASSERT(col < ia->cols);
1218	for (r = 0; r < ia->rows; r++) {
1219		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1220		    HAL_INI_VAL(ia, r, col));
1221
1222		/* Analog shift register delay seems needed for Merlin - PR kern/154220 */
1223		if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
1224			OS_DELAY(100);
1225
1226		DMA_YIELD(regWr);
1227	}
1228	return regWr;
1229}
1230
1231void
1232ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1233{
1234	int r;
1235
1236	HALASSERT(col < ia->cols);
1237	for (r = 0; r < ia->rows; r++)
1238		data[r] = HAL_INI_VAL(ia, r, col);
1239}
1240
1241int
1242ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1243	const uint32_t data[], int regWr)
1244{
1245	int r;
1246
1247	for (r = 0; r < ia->rows; r++) {
1248		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1249		DMA_YIELD(regWr);
1250	}
1251	return regWr;
1252}
1253
1254/*
1255 * These are EEPROM board related routines which should likely live in
1256 * a helper library of some sort.
1257 */
1258
1259/**************************************************************
1260 * ath_ee_getLowerUppderIndex
1261 *
1262 * Return indices surrounding the value in sorted integer lists.
1263 * Requirement: the input list must be monotonically increasing
1264 *     and populated up to the list size
1265 * Returns: match is set if an index in the array matches exactly
1266 *     or a the target is before or after the range of the array.
1267 */
1268HAL_BOOL
1269ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1270                   uint16_t *indexL, uint16_t *indexR)
1271{
1272    uint16_t i;
1273
1274    /*
1275     * Check first and last elements for beyond ordered array cases.
1276     */
1277    if (target <= pList[0]) {
1278        *indexL = *indexR = 0;
1279        return AH_TRUE;
1280    }
1281    if (target >= pList[listSize-1]) {
1282        *indexL = *indexR = (uint16_t)(listSize - 1);
1283        return AH_TRUE;
1284    }
1285
1286    /* look for value being near or between 2 values in list */
1287    for (i = 0; i < listSize - 1; i++) {
1288        /*
1289         * If value is close to the current value of the list
1290         * then target is not between values, it is one of the values
1291         */
1292        if (pList[i] == target) {
1293            *indexL = *indexR = i;
1294            return AH_TRUE;
1295        }
1296        /*
1297         * Look for value being between current value and next value
1298         * if so return these 2 values
1299         */
1300        if (target < pList[i + 1]) {
1301            *indexL = i;
1302            *indexR = (uint16_t)(i + 1);
1303            return AH_FALSE;
1304        }
1305    }
1306    HALASSERT(0);
1307    *indexL = *indexR = 0;
1308    return AH_FALSE;
1309}
1310
1311/**************************************************************
1312 * ath_ee_FillVpdTable
1313 *
1314 * Fill the Vpdlist for indices Pmax-Pmin
1315 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1316 */
1317HAL_BOOL
1318ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1319                   uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1320{
1321    uint16_t  i, k;
1322    uint8_t   currPwr = pwrMin;
1323    uint16_t  idxL, idxR;
1324
1325    HALASSERT(pwrMax > pwrMin);
1326    for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1327        ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1328                           &(idxL), &(idxR));
1329        if (idxR < 1)
1330            idxR = 1;           /* extrapolate below */
1331        if (idxL == numIntercepts - 1)
1332            idxL = (uint16_t)(numIntercepts - 2);   /* extrapolate above */
1333        if (pPwrList[idxL] == pPwrList[idxR])
1334            k = pVpdList[idxL];
1335        else
1336            k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1337                  (pPwrList[idxR] - pPwrList[idxL]) );
1338        HALASSERT(k < 256);
1339        pRetVpdList[i] = (uint8_t)k;
1340        currPwr += 2;               /* half dB steps */
1341    }
1342
1343    return AH_TRUE;
1344}
1345
1346/**************************************************************************
1347 * ath_ee_interpolate
1348 *
1349 * Returns signed interpolated or the scaled up interpolated value
1350 */
1351int16_t
1352ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1353            int16_t targetLeft, int16_t targetRight)
1354{
1355    int16_t rv;
1356
1357    if (srcRight == srcLeft) {
1358        rv = targetLeft;
1359    } else {
1360        rv = (int16_t)( ((target - srcLeft) * targetRight +
1361              (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1362    }
1363    return rv;
1364}
1365
1366/*
1367 * Adjust the TSF.
1368 */
1369void
1370ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
1371{
1372	/* XXX handle wrap/overflow */
1373	OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
1374}
1375
1376/*
1377 * Enable or disable CCA.
1378 */
1379void
1380ath_hal_setcca(struct ath_hal *ah, int ena)
1381{
1382	/*
1383	 * NB: fill me in; this is not provided by default because disabling
1384	 *     CCA in most locales violates regulatory.
1385	 */
1386}
1387
1388/*
1389 * Get CCA setting.
1390 */
1391int
1392ath_hal_getcca(struct ath_hal *ah)
1393{
1394	u_int32_t diag;
1395	if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
1396		return 1;
1397	return ((diag & 0x500000) == 0);
1398}
1399
1400/*
1401 * This routine is only needed when supporting EEPROM-in-RAM setups
1402 * (eg embedded SoCs and on-board PCI/PCIe devices.)
1403 */
1404/* NB: This is in 16 bit words; not bytes */
1405/* XXX This doesn't belong here!  */
1406#define ATH_DATA_EEPROM_SIZE    2048
1407
1408HAL_BOOL
1409ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data)
1410{
1411	if (ah->ah_eepromdata == AH_NULL) {
1412		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__);
1413		return AH_FALSE;
1414	}
1415	if (off > ATH_DATA_EEPROM_SIZE) {
1416		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n",
1417		    __func__, off, ATH_DATA_EEPROM_SIZE);
1418		return AH_FALSE;
1419	}
1420	(*data) = ah->ah_eepromdata[off];
1421	return AH_TRUE;
1422}
1423
1424/*
1425 * Do a 2GHz specific MHz->IEEE based on the hardware
1426 * frequency.
1427 *
1428 * This is the unmapped frequency which is programmed into the hardware.
1429 */
1430int
1431ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, int freq)
1432{
1433
1434	if (freq == 2484)
1435		return 14;
1436	if (freq < 2484)
1437		return ((int) freq - 2407) / 5;
1438	else
1439		return 15 + ((freq - 2512) / 20);
1440}
1441
1442/*
1443 * Clear the current survey data.
1444 *
1445 * This should be done during a channel change.
1446 */
1447void
1448ath_hal_survey_clear(struct ath_hal *ah)
1449{
1450
1451	OS_MEMZERO(&AH_PRIVATE(ah)->ah_chansurvey,
1452	    sizeof(AH_PRIVATE(ah)->ah_chansurvey));
1453}
1454
1455/*
1456 * Add a sample to the channel survey.
1457 */
1458void
1459ath_hal_survey_add_sample(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs)
1460{
1461	HAL_CHANNEL_SURVEY *cs;
1462
1463	cs = &AH_PRIVATE(ah)->ah_chansurvey;
1464
1465	OS_MEMCPY(&cs->samples[cs->cur_sample], hs, sizeof(*hs));
1466	cs->samples[cs->cur_sample].seq_num = cs->cur_seq;
1467	cs->cur_sample = (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT;
1468	cs->cur_seq++;
1469}
1470