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