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