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