xref: /freebsd/sys/dev/ath/ath_hal/ah.c (revision ddd5b8e9b4d8957fce018c520657cdfa4ecffad3)
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 
518 	/* Compensate for half/quarter rate */
519 	if (c != AH_NULL && IEEE80211_IS_CHAN_HALF(c))
520 		clks = clks / 2;
521 	else if (c != AH_NULL && IEEE80211_IS_CHAN_QUARTER(c))
522 		clks = clks / 4;
523 
524 	return clks;
525 }
526 
527 u_int
528 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
529 {
530 	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
531 	u_int usec;
532 
533 	/* NB: ah_curchan may be null when called attach time */
534 	/* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
535 	if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
536 		usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
537 		if (IEEE80211_IS_CHAN_HT40(c))
538 			usec >>= 1;
539 	} else if (c != AH_NULL) {
540 		usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
541 		if (IEEE80211_IS_CHAN_HT40(c))
542 			usec >>= 1;
543 	} else
544 		usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
545 	return usec;
546 }
547 
548 /*
549  * Setup a h/w rate table's reverse lookup table and
550  * fill in ack durations.  This routine is called for
551  * each rate table returned through the ah_getRateTable
552  * method.  The reverse lookup tables are assumed to be
553  * initialized to zero (or at least the first entry).
554  * We use this as a key that indicates whether or not
555  * we've previously setup the reverse lookup table.
556  *
557  * XXX not reentrant, but shouldn't matter
558  */
559 void
560 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
561 {
562 #define	N(a)	(sizeof(a)/sizeof(a[0]))
563 	int i;
564 
565 	if (rt->rateCodeToIndex[0] != 0)	/* already setup */
566 		return;
567 	for (i = 0; i < N(rt->rateCodeToIndex); i++)
568 		rt->rateCodeToIndex[i] = (uint8_t) -1;
569 	for (i = 0; i < rt->rateCount; i++) {
570 		uint8_t code = rt->info[i].rateCode;
571 		uint8_t cix = rt->info[i].controlRate;
572 
573 		HALASSERT(code < N(rt->rateCodeToIndex));
574 		rt->rateCodeToIndex[code] = i;
575 		HALASSERT((code | rt->info[i].shortPreamble) <
576 		    N(rt->rateCodeToIndex));
577 		rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
578 		/*
579 		 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
580 		 *     depends on whether they are marked as basic rates;
581 		 *     the static tables are setup with an 11b-compatible
582 		 *     2Mb/s rate which will work but is suboptimal
583 		 */
584 		rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
585 			WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
586 		rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
587 			WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
588 	}
589 #undef N
590 }
591 
592 HAL_STATUS
593 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
594 	uint32_t capability, uint32_t *result)
595 {
596 	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
597 
598 	switch (type) {
599 	case HAL_CAP_REG_DMN:		/* regulatory domain */
600 		*result = AH_PRIVATE(ah)->ah_currentRD;
601 		return HAL_OK;
602 	case HAL_CAP_DFS_DMN:		/* DFS Domain */
603 		*result = AH_PRIVATE(ah)->ah_dfsDomain;
604 		return HAL_OK;
605 	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
606 	case HAL_CAP_TKIP_MIC:		/* handle TKIP MIC in hardware */
607 		return HAL_ENOTSUPP;
608 	case HAL_CAP_TKIP_SPLIT:	/* hardware TKIP uses split keys */
609 		return HAL_ENOTSUPP;
610 	case HAL_CAP_PHYCOUNTERS:	/* hardware PHY error counters */
611 		return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
612 	case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
613 		return HAL_ENOTSUPP;
614 	case HAL_CAP_DIVERSITY:		/* hardware supports fast diversity */
615 		return HAL_ENOTSUPP;
616 	case HAL_CAP_KEYCACHE_SIZE:	/* hardware key cache size */
617 		*result =  pCap->halKeyCacheSize;
618 		return HAL_OK;
619 	case HAL_CAP_NUM_TXQUEUES:	/* number of hardware tx queues */
620 		*result = pCap->halTotalQueues;
621 		return HAL_OK;
622 	case HAL_CAP_VEOL:		/* hardware supports virtual EOL */
623 		return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
624 	case HAL_CAP_PSPOLL:		/* hardware PS-Poll support works */
625 		return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
626 	case HAL_CAP_COMPRESSION:
627 		return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
628 	case HAL_CAP_BURST:
629 		return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
630 	case HAL_CAP_FASTFRAME:
631 		return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
632 	case HAL_CAP_DIAG:		/* hardware diagnostic support */
633 		*result = AH_PRIVATE(ah)->ah_diagreg;
634 		return HAL_OK;
635 	case HAL_CAP_TXPOW:		/* global tx power limit  */
636 		switch (capability) {
637 		case 0:			/* facility is supported */
638 			return HAL_OK;
639 		case 1:			/* current limit */
640 			*result = AH_PRIVATE(ah)->ah_powerLimit;
641 			return HAL_OK;
642 		case 2:			/* current max tx power */
643 			*result = AH_PRIVATE(ah)->ah_maxPowerLevel;
644 			return HAL_OK;
645 		case 3:			/* scale factor */
646 			*result = AH_PRIVATE(ah)->ah_tpScale;
647 			return HAL_OK;
648 		}
649 		return HAL_ENOTSUPP;
650 	case HAL_CAP_BSSIDMASK:		/* hardware supports bssid mask */
651 		return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
652 	case HAL_CAP_MCAST_KEYSRCH:	/* multicast frame keycache search */
653 		return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
654 	case HAL_CAP_TSF_ADJUST:	/* hardware has beacon tsf adjust */
655 		return HAL_ENOTSUPP;
656 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
657 		switch (capability) {
658 		case 0:			/* facility is supported */
659 			return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
660 		case 1:			/* current setting */
661 			return AH_PRIVATE(ah)->ah_rfkillEnabled ?
662 				HAL_OK : HAL_ENOTSUPP;
663 		case 2:			/* rfsilent config */
664 			*result = AH_PRIVATE(ah)->ah_rfsilent;
665 			return HAL_OK;
666 		}
667 		return HAL_ENOTSUPP;
668 	case HAL_CAP_11D:
669 		return HAL_OK;
670 
671 	case HAL_CAP_HT:
672 		return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
673 	case HAL_CAP_GTXTO:
674 		return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
675 	case HAL_CAP_FAST_CC:
676 		return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
677 	case HAL_CAP_TX_CHAINMASK:	/* mask of TX chains supported */
678 		*result = pCap->halTxChainMask;
679 		return HAL_OK;
680 	case HAL_CAP_RX_CHAINMASK:	/* mask of RX chains supported */
681 		*result = pCap->halRxChainMask;
682 		return HAL_OK;
683 	case HAL_CAP_NUM_GPIO_PINS:
684 		*result = pCap->halNumGpioPins;
685 		return HAL_OK;
686 	case HAL_CAP_CST:
687 		return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
688 	case HAL_CAP_RTS_AGGR_LIMIT:
689 		*result = pCap->halRtsAggrLimit;
690 		return HAL_OK;
691 	case HAL_CAP_4ADDR_AGGR:
692 		return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
693 	case HAL_CAP_EXT_CHAN_DFS:
694 		return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
695 	case HAL_CAP_RX_STBC:
696 		return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
697 	case HAL_CAP_TX_STBC:
698 		return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
699 	case HAL_CAP_COMBINED_RADAR_RSSI:
700 		return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
701 	case HAL_CAP_AUTO_SLEEP:
702 		return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
703 	case HAL_CAP_MBSSID_AGGR_SUPPORT:
704 		return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
705 	case HAL_CAP_SPLIT_4KB_TRANS:	/* hardware handles descriptors straddling 4k page boundary */
706 		return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
707 	case HAL_CAP_REG_FLAG:
708 		*result = AH_PRIVATE(ah)->ah_currentRDext;
709 		return HAL_OK;
710 	case HAL_CAP_ENHANCED_DMA_SUPPORT:
711 		return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP;
712 	case HAL_CAP_NUM_TXMAPS:
713 		*result = pCap->halNumTxMaps;
714 		return HAL_OK;
715 	case HAL_CAP_TXDESCLEN:
716 		*result = pCap->halTxDescLen;
717 		return HAL_OK;
718 	case HAL_CAP_TXSTATUSLEN:
719 		*result = pCap->halTxStatusLen;
720 		return HAL_OK;
721 	case HAL_CAP_RXSTATUSLEN:
722 		*result = pCap->halRxStatusLen;
723 		return HAL_OK;
724 	case HAL_CAP_RXFIFODEPTH:
725 		switch (capability) {
726 		case HAL_RX_QUEUE_HP:
727 			*result = pCap->halRxHpFifoDepth;
728 			return HAL_OK;
729 		case HAL_RX_QUEUE_LP:
730 			*result = pCap->halRxLpFifoDepth;
731 			return HAL_OK;
732 		default:
733 			return HAL_ENOTSUPP;
734 	}
735 	case HAL_CAP_RXBUFSIZE:
736 	case HAL_CAP_NUM_MR_RETRIES:
737 		*result = pCap->halNumMRRetries;
738 		return HAL_OK;
739 	case HAL_CAP_BT_COEX:
740 		return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
741 	case HAL_CAP_SPECTRAL_SCAN:
742 		return pCap->halSpectralScanSupport ? HAL_OK : HAL_ENOTSUPP;
743 	case HAL_CAP_HT20_SGI:
744 		return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
745 	case HAL_CAP_RXTSTAMP_PREC:	/* rx desc tstamp precision (bits) */
746 		*result = pCap->halTstampPrecision;
747 		return HAL_OK;
748 	case HAL_CAP_ENHANCED_DFS_SUPPORT:
749 		return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
750 
751 	/* FreeBSD-specific entries for now */
752 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
753 		return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
754 	case HAL_CAP_INTRMASK:		/* mask of supported interrupts */
755 		*result = pCap->halIntrMask;
756 		return HAL_OK;
757 	case HAL_CAP_BSSIDMATCH:	/* hardware has disable bssid match */
758 		return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
759 	case HAL_CAP_STREAMS:		/* number of 11n spatial streams */
760 		switch (capability) {
761 		case 0:			/* TX */
762 			*result = pCap->halTxStreams;
763 			return HAL_OK;
764 		case 1:			/* RX */
765 			*result = pCap->halRxStreams;
766 			return HAL_OK;
767 		default:
768 			return HAL_ENOTSUPP;
769 		}
770 	case HAL_CAP_RXDESC_SELFLINK:	/* hardware supports self-linked final RX descriptors correctly */
771 		return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
772 	case HAL_CAP_LONG_RXDESC_TSF:		/* 32 bit TSF in RX descriptor? */
773 		return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP;
774 	case HAL_CAP_BB_READ_WAR:		/* Baseband read WAR */
775 		return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP;
776 	case HAL_CAP_SERIALISE_WAR:		/* PCI register serialisation */
777 		return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP;
778 	case HAL_CAP_MFP:			/* Management frame protection setting */
779 		*result = pCap->halMfpSupport;
780 		return HAL_OK;
781 	default:
782 		return HAL_EINVAL;
783 	}
784 }
785 
786 HAL_BOOL
787 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
788 	uint32_t capability, uint32_t setting, HAL_STATUS *status)
789 {
790 
791 	switch (type) {
792 	case HAL_CAP_TXPOW:
793 		switch (capability) {
794 		case 3:
795 			if (setting <= HAL_TP_SCALE_MIN) {
796 				AH_PRIVATE(ah)->ah_tpScale = setting;
797 				return AH_TRUE;
798 			}
799 			break;
800 		}
801 		break;
802 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
803 		/*
804 		 * NB: allow even if halRfSilentSupport is false
805 		 *     in case the EEPROM is misprogrammed.
806 		 */
807 		switch (capability) {
808 		case 1:			/* current setting */
809 			AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
810 			return AH_TRUE;
811 		case 2:			/* rfsilent config */
812 			/* XXX better done per-chip for validation? */
813 			AH_PRIVATE(ah)->ah_rfsilent = setting;
814 			return AH_TRUE;
815 		}
816 		break;
817 	case HAL_CAP_REG_DMN:		/* regulatory domain */
818 		AH_PRIVATE(ah)->ah_currentRD = setting;
819 		return AH_TRUE;
820 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
821 		AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
822 		return AH_TRUE;
823 	default:
824 		break;
825 	}
826 	if (status)
827 		*status = HAL_EINVAL;
828 	return AH_FALSE;
829 }
830 
831 /*
832  * Common support for getDiagState method.
833  */
834 
835 static u_int
836 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
837 	void *dstbuf, int space)
838 {
839 	uint32_t *dp = dstbuf;
840 	int i;
841 
842 	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
843 		u_int r = regs[i].start;
844 		u_int e = regs[i].end;
845 		*dp++ = (r<<16) | e;
846 		space -= sizeof(uint32_t);
847 		do {
848 			*dp++ = OS_REG_READ(ah, r);
849 			r += sizeof(uint32_t);
850 			space -= sizeof(uint32_t);
851 		} while (r <= e && space >= sizeof(uint32_t));
852 	}
853 	return (char *) dp - (char *) dstbuf;
854 }
855 
856 static void
857 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
858 {
859 	while (space >= sizeof(HAL_REGWRITE)) {
860 		OS_REG_WRITE(ah, regs->addr, regs->value);
861 		regs++, space -= sizeof(HAL_REGWRITE);
862 	}
863 }
864 
865 HAL_BOOL
866 ath_hal_getdiagstate(struct ath_hal *ah, int request,
867 	const void *args, uint32_t argsize,
868 	void **result, uint32_t *resultsize)
869 {
870 	switch (request) {
871 	case HAL_DIAG_REVS:
872 		*result = &AH_PRIVATE(ah)->ah_devid;
873 		*resultsize = sizeof(HAL_REVS);
874 		return AH_TRUE;
875 	case HAL_DIAG_REGS:
876 		*resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
877 		return AH_TRUE;
878 	case HAL_DIAG_SETREGS:
879 		ath_hal_setregs(ah, args, argsize);
880 		*resultsize = 0;
881 		return AH_TRUE;
882 	case HAL_DIAG_FATALERR:
883 		*result = &AH_PRIVATE(ah)->ah_fatalState[0];
884 		*resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
885 		return AH_TRUE;
886 	case HAL_DIAG_EEREAD:
887 		if (argsize != sizeof(uint16_t))
888 			return AH_FALSE;
889 		if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
890 			return AH_FALSE;
891 		*resultsize = sizeof(uint16_t);
892 		return AH_TRUE;
893 #ifdef AH_PRIVATE_DIAG
894 	case HAL_DIAG_SETKEY: {
895 		const HAL_DIAG_KEYVAL *dk;
896 
897 		if (argsize != sizeof(HAL_DIAG_KEYVAL))
898 			return AH_FALSE;
899 		dk = (const HAL_DIAG_KEYVAL *)args;
900 		return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
901 			&dk->dk_keyval, dk->dk_mac, dk->dk_xor);
902 	}
903 	case HAL_DIAG_RESETKEY:
904 		if (argsize != sizeof(uint16_t))
905 			return AH_FALSE;
906 		return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
907 #ifdef AH_SUPPORT_WRITE_EEPROM
908 	case HAL_DIAG_EEWRITE: {
909 		const HAL_DIAG_EEVAL *ee;
910 		if (argsize != sizeof(HAL_DIAG_EEVAL))
911 			return AH_FALSE;
912 		ee = (const HAL_DIAG_EEVAL *)args;
913 		return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
914 	}
915 #endif /* AH_SUPPORT_WRITE_EEPROM */
916 #endif /* AH_PRIVATE_DIAG */
917 	case HAL_DIAG_11NCOMPAT:
918 		if (argsize == 0) {
919 			*resultsize = sizeof(uint32_t);
920 			*((uint32_t *)(*result)) =
921 				AH_PRIVATE(ah)->ah_11nCompat;
922 		} else if (argsize == sizeof(uint32_t)) {
923 			AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
924 		} else
925 			return AH_FALSE;
926 		return AH_TRUE;
927 	}
928 	return AH_FALSE;
929 }
930 
931 /*
932  * Set the properties of the tx queue with the parameters
933  * from qInfo.
934  */
935 HAL_BOOL
936 ath_hal_setTxQProps(struct ath_hal *ah,
937 	HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
938 {
939 	uint32_t cw;
940 
941 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
942 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
943 		    "%s: inactive queue\n", __func__);
944 		return AH_FALSE;
945 	}
946 	/* XXX validate parameters */
947 	qi->tqi_ver = qInfo->tqi_ver;
948 	qi->tqi_subtype = qInfo->tqi_subtype;
949 	qi->tqi_qflags = qInfo->tqi_qflags;
950 	qi->tqi_priority = qInfo->tqi_priority;
951 	if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
952 		qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
953 	else
954 		qi->tqi_aifs = INIT_AIFS;
955 	if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
956 		cw = AH_MIN(qInfo->tqi_cwmin, 1024);
957 		/* make sure that the CWmin is of the form (2^n - 1) */
958 		qi->tqi_cwmin = 1;
959 		while (qi->tqi_cwmin < cw)
960 			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
961 	} else
962 		qi->tqi_cwmin = qInfo->tqi_cwmin;
963 	if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
964 		cw = AH_MIN(qInfo->tqi_cwmax, 1024);
965 		/* make sure that the CWmax is of the form (2^n - 1) */
966 		qi->tqi_cwmax = 1;
967 		while (qi->tqi_cwmax < cw)
968 			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
969 	} else
970 		qi->tqi_cwmax = INIT_CWMAX;
971 	/* Set retry limit values */
972 	if (qInfo->tqi_shretry != 0)
973 		qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
974 	else
975 		qi->tqi_shretry = INIT_SH_RETRY;
976 	if (qInfo->tqi_lgretry != 0)
977 		qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
978 	else
979 		qi->tqi_lgretry = INIT_LG_RETRY;
980 	qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
981 	qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
982 	qi->tqi_burstTime = qInfo->tqi_burstTime;
983 	qi->tqi_readyTime = qInfo->tqi_readyTime;
984 
985 	switch (qInfo->tqi_subtype) {
986 	case HAL_WME_UPSD:
987 		if (qi->tqi_type == HAL_TX_QUEUE_DATA)
988 			qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
989 		break;
990 	default:
991 		break;		/* NB: silence compiler */
992 	}
993 	return AH_TRUE;
994 }
995 
996 HAL_BOOL
997 ath_hal_getTxQProps(struct ath_hal *ah,
998 	HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
999 {
1000 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
1001 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
1002 		    "%s: inactive queue\n", __func__);
1003 		return AH_FALSE;
1004 	}
1005 
1006 	qInfo->tqi_qflags = qi->tqi_qflags;
1007 	qInfo->tqi_ver = qi->tqi_ver;
1008 	qInfo->tqi_subtype = qi->tqi_subtype;
1009 	qInfo->tqi_qflags = qi->tqi_qflags;
1010 	qInfo->tqi_priority = qi->tqi_priority;
1011 	qInfo->tqi_aifs = qi->tqi_aifs;
1012 	qInfo->tqi_cwmin = qi->tqi_cwmin;
1013 	qInfo->tqi_cwmax = qi->tqi_cwmax;
1014 	qInfo->tqi_shretry = qi->tqi_shretry;
1015 	qInfo->tqi_lgretry = qi->tqi_lgretry;
1016 	qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
1017 	qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
1018 	qInfo->tqi_burstTime = qi->tqi_burstTime;
1019 	qInfo->tqi_readyTime = qi->tqi_readyTime;
1020 	return AH_TRUE;
1021 }
1022 
1023                                      /* 11a Turbo  11b  11g  108g */
1024 static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
1025 
1026 /*
1027  * Read the current channel noise floor and return.
1028  * If nf cal hasn't finished, channel noise floor should be 0
1029  * and we return a nominal value based on band and frequency.
1030  *
1031  * NB: This is a private routine used by per-chip code to
1032  *     implement the ah_getChanNoise method.
1033  */
1034 int16_t
1035 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
1036 {
1037 	HAL_CHANNEL_INTERNAL *ichan;
1038 
1039 	ichan = ath_hal_checkchannel(ah, chan);
1040 	if (ichan == AH_NULL) {
1041 		HALDEBUG(ah, HAL_DEBUG_NFCAL,
1042 		    "%s: invalid channel %u/0x%x; no mapping\n",
1043 		    __func__, chan->ic_freq, chan->ic_flags);
1044 		return 0;
1045 	}
1046 	if (ichan->rawNoiseFloor == 0) {
1047 		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1048 
1049 		HALASSERT(mode < WIRELESS_MODE_MAX);
1050 		return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
1051 	} else
1052 		return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
1053 }
1054 
1055 /*
1056  * Fetch the current setup of ctl/ext noise floor values.
1057  *
1058  * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
1059  * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
1060  *
1061  * The caller must supply ctl/ext NF arrays which are at least
1062  * AH_MAX_CHAINS entries long.
1063  */
1064 int
1065 ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
1066     const struct ieee80211_channel *chan, int16_t *nf_ctl,
1067     int16_t *nf_ext)
1068 {
1069 #ifdef	AH_SUPPORT_AR5416
1070 	HAL_CHANNEL_INTERNAL *ichan;
1071 	int i;
1072 
1073 	ichan = ath_hal_checkchannel(ah, chan);
1074 	if (ichan == AH_NULL) {
1075 		HALDEBUG(ah, HAL_DEBUG_NFCAL,
1076 		    "%s: invalid channel %u/0x%x; no mapping\n",
1077 		    __func__, chan->ic_freq, chan->ic_flags);
1078 		for (i = 0; i < AH_MAX_CHAINS; i++) {
1079 			nf_ctl[i] = nf_ext[i] = 0;
1080 		}
1081 		return 0;
1082 	}
1083 
1084 	/* Return 0 if there's no valid MIMO values (yet) */
1085 	if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
1086 		for (i = 0; i < AH_MAX_CHAINS; i++) {
1087 			nf_ctl[i] = nf_ext[i] = 0;
1088 		}
1089 		return 0;
1090 	}
1091 	if (ichan->rawNoiseFloor == 0) {
1092 		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1093 		HALASSERT(mode < WIRELESS_MODE_MAX);
1094 		/*
1095 		 * See the comment below - this could cause issues for
1096 		 * stations which have a very low RSSI, below the
1097 		 * 'normalised' NF values in NOISE_FLOOR[].
1098 		 */
1099 		for (i = 0; i < AH_MAX_CHAINS; i++) {
1100 			nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
1101 			    ath_hal_getNfAdjust(ah, ichan);
1102 		}
1103 		return 1;
1104 	} else {
1105 		/*
1106 		 * The value returned here from a MIMO radio is presumed to be
1107 		 * "good enough" as a NF calculation. As RSSI values are calculated
1108 		 * against this, an adjusted NF may be higher than the RSSI value
1109 		 * returned from a vary weak station, resulting in an obscenely
1110 		 * high signal strength calculation being returned.
1111 		 *
1112 		 * This should be re-evaluated at a later date, along with any
1113 		 * signal strength calculations which are made. Quite likely the
1114 		 * RSSI values will need to be adjusted to ensure the calculations
1115 		 * don't "wrap" when RSSI is less than the "adjusted" NF value.
1116 		 * ("Adjust" here is via ichan->noiseFloorAdjust.)
1117 		 */
1118 		for (i = 0; i < AH_MAX_CHAINS; i++) {
1119 			nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
1120 			nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
1121 		}
1122 		return 1;
1123 	}
1124 #else
1125 	return 0;
1126 #endif	/* AH_SUPPORT_AR5416 */
1127 }
1128 
1129 /*
1130  * Process all valid raw noise floors into the dBm noise floor values.
1131  * Though our device has no reference for a dBm noise floor, we perform
1132  * a relative minimization of NF's based on the lowest NF found across a
1133  * channel scan.
1134  */
1135 void
1136 ath_hal_process_noisefloor(struct ath_hal *ah)
1137 {
1138 	HAL_CHANNEL_INTERNAL *c;
1139 	int16_t correct2, correct5;
1140 	int16_t lowest2, lowest5;
1141 	int i;
1142 
1143 	/*
1144 	 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
1145 	 * for statistically recorded NF/channel deviation.
1146 	 */
1147 	correct2 = lowest2 = 0;
1148 	correct5 = lowest5 = 0;
1149 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1150 		WIRELESS_MODE mode;
1151 		int16_t nf;
1152 
1153 		c = &AH_PRIVATE(ah)->ah_channels[i];
1154 		if (c->rawNoiseFloor >= 0)
1155 			continue;
1156 		/* XXX can't identify proper mode */
1157 		mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
1158 		nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
1159 			ath_hal_getNfAdjust(ah, c);
1160 		if (IS_CHAN_5GHZ(c)) {
1161 			if (nf < lowest5) {
1162 				lowest5 = nf;
1163 				correct5 = NOISE_FLOOR[mode] -
1164 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1165 			}
1166 		} else {
1167 			if (nf < lowest2) {
1168 				lowest2 = nf;
1169 				correct2 = NOISE_FLOOR[mode] -
1170 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1171 			}
1172 		}
1173 	}
1174 
1175 	/* Correct the channels to reach the expected NF value */
1176 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1177 		c = &AH_PRIVATE(ah)->ah_channels[i];
1178 		if (c->rawNoiseFloor >= 0)
1179 			continue;
1180 		/* Apply correction factor */
1181 		c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
1182 			(IS_CHAN_5GHZ(c) ? correct5 : correct2);
1183 		HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
1184 		    c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
1185 	}
1186 }
1187 
1188 /*
1189  * INI support routines.
1190  */
1191 
1192 int
1193 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1194 	int col, int regWr)
1195 {
1196 	int r;
1197 
1198 	HALASSERT(col < ia->cols);
1199 	for (r = 0; r < ia->rows; r++) {
1200 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1201 		    HAL_INI_VAL(ia, r, col));
1202 
1203 		/* Analog shift register delay seems needed for Merlin - PR kern/154220 */
1204 		if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
1205 			OS_DELAY(100);
1206 
1207 		DMA_YIELD(regWr);
1208 	}
1209 	return regWr;
1210 }
1211 
1212 void
1213 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1214 {
1215 	int r;
1216 
1217 	HALASSERT(col < ia->cols);
1218 	for (r = 0; r < ia->rows; r++)
1219 		data[r] = HAL_INI_VAL(ia, r, col);
1220 }
1221 
1222 int
1223 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1224 	const uint32_t data[], int regWr)
1225 {
1226 	int r;
1227 
1228 	for (r = 0; r < ia->rows; r++) {
1229 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1230 		DMA_YIELD(regWr);
1231 	}
1232 	return regWr;
1233 }
1234 
1235 /*
1236  * These are EEPROM board related routines which should likely live in
1237  * a helper library of some sort.
1238  */
1239 
1240 /**************************************************************
1241  * ath_ee_getLowerUppderIndex
1242  *
1243  * Return indices surrounding the value in sorted integer lists.
1244  * Requirement: the input list must be monotonically increasing
1245  *     and populated up to the list size
1246  * Returns: match is set if an index in the array matches exactly
1247  *     or a the target is before or after the range of the array.
1248  */
1249 HAL_BOOL
1250 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1251                    uint16_t *indexL, uint16_t *indexR)
1252 {
1253     uint16_t i;
1254 
1255     /*
1256      * Check first and last elements for beyond ordered array cases.
1257      */
1258     if (target <= pList[0]) {
1259         *indexL = *indexR = 0;
1260         return AH_TRUE;
1261     }
1262     if (target >= pList[listSize-1]) {
1263         *indexL = *indexR = (uint16_t)(listSize - 1);
1264         return AH_TRUE;
1265     }
1266 
1267     /* look for value being near or between 2 values in list */
1268     for (i = 0; i < listSize - 1; i++) {
1269         /*
1270          * If value is close to the current value of the list
1271          * then target is not between values, it is one of the values
1272          */
1273         if (pList[i] == target) {
1274             *indexL = *indexR = i;
1275             return AH_TRUE;
1276         }
1277         /*
1278          * Look for value being between current value and next value
1279          * if so return these 2 values
1280          */
1281         if (target < pList[i + 1]) {
1282             *indexL = i;
1283             *indexR = (uint16_t)(i + 1);
1284             return AH_FALSE;
1285         }
1286     }
1287     HALASSERT(0);
1288     *indexL = *indexR = 0;
1289     return AH_FALSE;
1290 }
1291 
1292 /**************************************************************
1293  * ath_ee_FillVpdTable
1294  *
1295  * Fill the Vpdlist for indices Pmax-Pmin
1296  * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1297  */
1298 HAL_BOOL
1299 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1300                    uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1301 {
1302     uint16_t  i, k;
1303     uint8_t   currPwr = pwrMin;
1304     uint16_t  idxL, idxR;
1305 
1306     HALASSERT(pwrMax > pwrMin);
1307     for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1308         ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1309                            &(idxL), &(idxR));
1310         if (idxR < 1)
1311             idxR = 1;           /* extrapolate below */
1312         if (idxL == numIntercepts - 1)
1313             idxL = (uint16_t)(numIntercepts - 2);   /* extrapolate above */
1314         if (pPwrList[idxL] == pPwrList[idxR])
1315             k = pVpdList[idxL];
1316         else
1317             k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1318                   (pPwrList[idxR] - pPwrList[idxL]) );
1319         HALASSERT(k < 256);
1320         pRetVpdList[i] = (uint8_t)k;
1321         currPwr += 2;               /* half dB steps */
1322     }
1323 
1324     return AH_TRUE;
1325 }
1326 
1327 /**************************************************************************
1328  * ath_ee_interpolate
1329  *
1330  * Returns signed interpolated or the scaled up interpolated value
1331  */
1332 int16_t
1333 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1334             int16_t targetLeft, int16_t targetRight)
1335 {
1336     int16_t rv;
1337 
1338     if (srcRight == srcLeft) {
1339         rv = targetLeft;
1340     } else {
1341         rv = (int16_t)( ((target - srcLeft) * targetRight +
1342               (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1343     }
1344     return rv;
1345 }
1346 
1347 /*
1348  * Adjust the TSF.
1349  */
1350 void
1351 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
1352 {
1353 	/* XXX handle wrap/overflow */
1354 	OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
1355 }
1356 
1357 /*
1358  * Enable or disable CCA.
1359  */
1360 void
1361 ath_hal_setcca(struct ath_hal *ah, int ena)
1362 {
1363 	/*
1364 	 * NB: fill me in; this is not provided by default because disabling
1365 	 *     CCA in most locales violates regulatory.
1366 	 */
1367 }
1368 
1369 /*
1370  * Get CCA setting.
1371  */
1372 int
1373 ath_hal_getcca(struct ath_hal *ah)
1374 {
1375 	u_int32_t diag;
1376 	if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
1377 		return 1;
1378 	return ((diag & 0x500000) == 0);
1379 }
1380 
1381 /*
1382  * This routine is only needed when supporting EEPROM-in-RAM setups
1383  * (eg embedded SoCs and on-board PCI/PCIe devices.)
1384  */
1385 /* NB: This is in 16 bit words; not bytes */
1386 /* XXX This doesn't belong here!  */
1387 #define ATH_DATA_EEPROM_SIZE    2048
1388 
1389 HAL_BOOL
1390 ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data)
1391 {
1392 	if (ah->ah_eepromdata == AH_NULL) {
1393 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__);
1394 		return AH_FALSE;
1395 	}
1396 	if (off > ATH_DATA_EEPROM_SIZE) {
1397 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n",
1398 		    __func__, off, ATH_DATA_EEPROM_SIZE);
1399 		return AH_FALSE;
1400 	}
1401 	(*data) = ah->ah_eepromdata[off];
1402 	return AH_TRUE;
1403 }
1404