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