xref: /freebsd/sys/dev/ath/ath_hal/ah.c (revision 0f27aaf940f2fa5a6540285537b33115a96161a4)
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 
25 #include "ar5416/ar5416reg.h"		/* NB: includes ar5212reg.h */
26 
27 /* linker set of registered chips */
28 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
29 
30 /*
31  * Check the set of registered chips to see if any recognize
32  * the device as one they can support.
33  */
34 const char*
35 ath_hal_probe(uint16_t vendorid, uint16_t devid)
36 {
37 	struct ath_hal_chip * const *pchip;
38 
39 	OS_SET_FOREACH(pchip, ah_chips) {
40 		const char *name = (*pchip)->probe(vendorid, devid);
41 		if (name != AH_NULL)
42 			return name;
43 	}
44 	return AH_NULL;
45 }
46 
47 /*
48  * Attach detects device chip revisions, initializes the hwLayer
49  * function list, reads EEPROM information,
50  * selects reset vectors, and performs a short self test.
51  * Any failures will return an error that should cause a hardware
52  * disable.
53  */
54 struct ath_hal*
55 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
56 	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *error)
57 {
58 	struct ath_hal_chip * const *pchip;
59 
60 	OS_SET_FOREACH(pchip, ah_chips) {
61 		struct ath_hal_chip *chip = *pchip;
62 		struct ath_hal *ah;
63 
64 		/* XXX don't have vendorid, assume atheros one works */
65 		if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
66 			continue;
67 		ah = chip->attach(devid, sc, st, sh, eepromdata, error);
68 		if (ah != AH_NULL) {
69 			/* copy back private state to public area */
70 			ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
71 			ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
72 			ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
73 			ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
74 			ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
75 			ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
76 			ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
77 			return ah;
78 		}
79 	}
80 	return AH_NULL;
81 }
82 
83 const char *
84 ath_hal_mac_name(struct ath_hal *ah)
85 {
86 	switch (ah->ah_macVersion) {
87 	case AR_SREV_VERSION_CRETE:
88 	case AR_SREV_VERSION_MAUI_1:
89 		return "5210";
90 	case AR_SREV_VERSION_MAUI_2:
91 	case AR_SREV_VERSION_OAHU:
92 		return "5211";
93 	case AR_SREV_VERSION_VENICE:
94 		return "5212";
95 	case AR_SREV_VERSION_GRIFFIN:
96 		return "2413";
97 	case AR_SREV_VERSION_CONDOR:
98 		return "5424";
99 	case AR_SREV_VERSION_EAGLE:
100 		return "5413";
101 	case AR_SREV_VERSION_COBRA:
102 		return "2415";
103 	case AR_SREV_2425:
104 		return "2425";
105 	case AR_SREV_2417:
106 		return "2417";
107 	case AR_XSREV_VERSION_OWL_PCI:
108 		return "5416";
109 	case AR_XSREV_VERSION_OWL_PCIE:
110 		return "5418";
111 	case AR_XSREV_VERSION_SOWL:
112 		return "9160";
113 	case AR_XSREV_VERSION_MERLIN:
114 		return "9280";
115 	case AR_XSREV_VERSION_KITE:
116 		return "9285";
117 	}
118 	return "????";
119 }
120 
121 /*
122  * Return the mask of available modes based on the hardware capabilities.
123  */
124 u_int
125 ath_hal_getwirelessmodes(struct ath_hal*ah)
126 {
127 	return ath_hal_getWirelessModes(ah);
128 }
129 
130 /* linker set of registered RF backends */
131 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
132 
133 /*
134  * Check the set of registered RF backends to see if
135  * any recognize the device as one they can support.
136  */
137 struct ath_hal_rf *
138 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
139 {
140 	struct ath_hal_rf * const *prf;
141 
142 	OS_SET_FOREACH(prf, ah_rfs) {
143 		struct ath_hal_rf *rf = *prf;
144 		if (rf->probe(ah))
145 			return rf;
146 	}
147 	*ecode = HAL_ENOTSUPP;
148 	return AH_NULL;
149 }
150 
151 const char *
152 ath_hal_rf_name(struct ath_hal *ah)
153 {
154 	switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
155 	case 0:			/* 5210 */
156 		return "5110";	/* NB: made up */
157 	case AR_RAD5111_SREV_MAJOR:
158 	case AR_RAD5111_SREV_PROD:
159 		return "5111";
160 	case AR_RAD2111_SREV_MAJOR:
161 		return "2111";
162 	case AR_RAD5112_SREV_MAJOR:
163 	case AR_RAD5112_SREV_2_0:
164 	case AR_RAD5112_SREV_2_1:
165 		return "5112";
166 	case AR_RAD2112_SREV_MAJOR:
167 	case AR_RAD2112_SREV_2_0:
168 	case AR_RAD2112_SREV_2_1:
169 		return "2112";
170 	case AR_RAD2413_SREV_MAJOR:
171 		return "2413";
172 	case AR_RAD5413_SREV_MAJOR:
173 		return "5413";
174 	case AR_RAD2316_SREV_MAJOR:
175 		return "2316";
176 	case AR_RAD2317_SREV_MAJOR:
177 		return "2317";
178 	case AR_RAD5424_SREV_MAJOR:
179 		return "5424";
180 
181 	case AR_RAD5133_SREV_MAJOR:
182 		return "5133";
183 	case AR_RAD2133_SREV_MAJOR:
184 		return "2133";
185 	case AR_RAD5122_SREV_MAJOR:
186 		return "5122";
187 	case AR_RAD2122_SREV_MAJOR:
188 		return "2122";
189 	}
190 	return "????";
191 }
192 
193 /*
194  * Poll the register looking for a specific value.
195  */
196 HAL_BOOL
197 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
198 {
199 #define	AH_TIMEOUT	1000
200 	return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
201 #undef AH_TIMEOUT
202 }
203 
204 HAL_BOOL
205 ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
206 {
207 	int i;
208 
209 	for (i = 0; i < timeout; i++) {
210 		if ((OS_REG_READ(ah, reg) & mask) == val)
211 			return AH_TRUE;
212 		OS_DELAY(10);
213 	}
214 	HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
215 	    "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
216 	    __func__, reg, OS_REG_READ(ah, reg), mask, val);
217 	return AH_FALSE;
218 }
219 
220 /*
221  * Reverse the bits starting at the low bit for a value of
222  * bit_count in size
223  */
224 uint32_t
225 ath_hal_reverseBits(uint32_t val, uint32_t n)
226 {
227 	uint32_t retval;
228 	int i;
229 
230 	for (i = 0, retval = 0; i < n; i++) {
231 		retval = (retval << 1) | (val & 1);
232 		val >>= 1;
233 	}
234 	return retval;
235 }
236 
237 /* 802.11n related timing definitions */
238 
239 #define	OFDM_PLCP_BITS	22
240 #define	HT_L_STF	8
241 #define	HT_L_LTF	8
242 #define	HT_L_SIG	4
243 #define	HT_SIG		8
244 #define	HT_STF		4
245 #define	HT_LTF(n)	((n) * 4)
246 
247 #define	HT_RC_2_MCS(_rc)	((_rc) & 0xf)
248 #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
249 #define	IS_HT_RATE(_rc)		( (_rc) & IEEE80211_RATE_MCS)
250 
251 /*
252  * Calculate the duration of a packet whether it is 11n or legacy.
253  */
254 uint32_t
255 ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
256     uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
257 {
258 	uint8_t rc;
259 	int numStreams;
260 
261 	rc = rates->info[rateix].rateCode;
262 
263 	/* Legacy rate? Return the old way */
264 	if (! IS_HT_RATE(rc))
265 		return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
266 
267 	/* 11n frame - extract out the number of spatial streams */
268 	numStreams = HT_RC_2_STREAMS(rc);
269 	KASSERT(numStreams == 1 || numStreams == 2, ("number of spatial streams needs to be 1 or 2: MCS rate 0x%x!", rateix));
270 
271 	return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
272 }
273 
274 /*
275  * Calculate the transmit duration of an 11n frame.
276  * This only works for MCS0->MCS15.
277  */
278 uint32_t
279 ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, HAL_BOOL isht40,
280     HAL_BOOL isShortGI)
281 {
282 	static const uint16_t ht20_bps[16] = {
283 	    26, 52, 78, 104, 156, 208, 234, 260,
284 	    52, 104, 156, 208, 312, 416, 468, 520
285 	};
286 	static const uint16_t ht40_bps[16] = {
287 	    54, 108, 162, 216, 324, 432, 486, 540,
288 	    108, 216, 324, 432, 648, 864, 972, 1080,
289 	};
290 	uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
291 
292 	KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
293 	KASSERT((rate &~ IEEE80211_RATE_MCS) < 16, ("bad mcs 0x%x", rate));
294 
295 	if (isht40)
296 		bitsPerSymbol = ht40_bps[rate & 0xf];
297 	else
298 		bitsPerSymbol = ht20_bps[rate & 0xf];
299 	numBits = OFDM_PLCP_BITS + (frameLen << 3);
300 	numSymbols = howmany(numBits, bitsPerSymbol);
301 	if (isShortGI)
302 		txTime = ((numSymbols * 18) + 4) / 5;   /* 3.6us */
303 	else
304 		txTime = numSymbols * 4;                /* 4us */
305 	return txTime + HT_L_STF + HT_L_LTF +
306 	    HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
307 }
308 
309 /*
310  * Compute the time to transmit a frame of length frameLen bytes
311  * using the specified rate, phy, and short preamble setting.
312  */
313 uint16_t
314 ath_hal_computetxtime(struct ath_hal *ah,
315 	const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
316 	HAL_BOOL shortPreamble)
317 {
318 	uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
319 	uint32_t kbps;
320 
321 	kbps = rates->info[rateix].rateKbps;
322 	/*
323 	 * index can be invalid duting dynamic Turbo transitions.
324 	 * XXX
325 	 */
326 	if (kbps == 0)
327 		return 0;
328 	switch (rates->info[rateix].phy) {
329 	case IEEE80211_T_CCK:
330 		phyTime		= CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
331 		if (shortPreamble && rates->info[rateix].shortPreamble)
332 			phyTime >>= 1;
333 		numBits		= frameLen << 3;
334 		txTime		= CCK_SIFS_TIME + phyTime
335 				+ ((numBits * 1000)/kbps);
336 		break;
337 	case IEEE80211_T_OFDM:
338 		bitsPerSymbol	= (kbps * OFDM_SYMBOL_TIME) / 1000;
339 		HALASSERT(bitsPerSymbol != 0);
340 
341 		numBits		= OFDM_PLCP_BITS + (frameLen << 3);
342 		numSymbols	= howmany(numBits, bitsPerSymbol);
343 		txTime		= OFDM_SIFS_TIME
344 				+ OFDM_PREAMBLE_TIME
345 				+ (numSymbols * OFDM_SYMBOL_TIME);
346 		break;
347 	case IEEE80211_T_OFDM_HALF:
348 		bitsPerSymbol	= (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
349 		HALASSERT(bitsPerSymbol != 0);
350 
351 		numBits		= OFDM_HALF_PLCP_BITS + (frameLen << 3);
352 		numSymbols	= howmany(numBits, bitsPerSymbol);
353 		txTime		= OFDM_HALF_SIFS_TIME
354 				+ OFDM_HALF_PREAMBLE_TIME
355 				+ (numSymbols * OFDM_HALF_SYMBOL_TIME);
356 		break;
357 	case IEEE80211_T_OFDM_QUARTER:
358 		bitsPerSymbol	= (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
359 		HALASSERT(bitsPerSymbol != 0);
360 
361 		numBits		= OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
362 		numSymbols	= howmany(numBits, bitsPerSymbol);
363 		txTime		= OFDM_QUARTER_SIFS_TIME
364 				+ OFDM_QUARTER_PREAMBLE_TIME
365 				+ (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
366 		break;
367 	case IEEE80211_T_TURBO:
368 		bitsPerSymbol	= (kbps * TURBO_SYMBOL_TIME) / 1000;
369 		HALASSERT(bitsPerSymbol != 0);
370 
371 		numBits		= TURBO_PLCP_BITS + (frameLen << 3);
372 		numSymbols	= howmany(numBits, bitsPerSymbol);
373 		txTime		= TURBO_SIFS_TIME
374 				+ TURBO_PREAMBLE_TIME
375 				+ (numSymbols * TURBO_SYMBOL_TIME);
376 		break;
377 	default:
378 		HALDEBUG(ah, HAL_DEBUG_PHYIO,
379 		    "%s: unknown phy %u (rate ix %u)\n",
380 		    __func__, rates->info[rateix].phy, rateix);
381 		txTime = 0;
382 		break;
383 	}
384 	return txTime;
385 }
386 
387 typedef enum {
388 	WIRELESS_MODE_11a   = 0,
389 	WIRELESS_MODE_TURBO = 1,
390 	WIRELESS_MODE_11b   = 2,
391 	WIRELESS_MODE_11g   = 3,
392 	WIRELESS_MODE_108g  = 4,
393 
394 	WIRELESS_MODE_MAX
395 } WIRELESS_MODE;
396 
397 static WIRELESS_MODE
398 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
399 {
400 	if (IEEE80211_IS_CHAN_B(chan))
401 		return WIRELESS_MODE_11b;
402 	if (IEEE80211_IS_CHAN_G(chan))
403 		return WIRELESS_MODE_11g;
404 	if (IEEE80211_IS_CHAN_108G(chan))
405 		return WIRELESS_MODE_108g;
406 	if (IEEE80211_IS_CHAN_TURBO(chan))
407 		return WIRELESS_MODE_TURBO;
408 	return WIRELESS_MODE_11a;
409 }
410 
411 /*
412  * Convert between microseconds and core system clocks.
413  */
414                                      /* 11a Turbo  11b  11g  108g */
415 static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
416 
417 u_int
418 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
419 {
420 	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
421 	u_int clks;
422 
423 	/* NB: ah_curchan may be null when called attach time */
424 	if (c != AH_NULL) {
425 		clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
426 		if (IEEE80211_IS_CHAN_HT40(c))
427 			clks <<= 1;
428 	} else
429 		clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
430 	return clks;
431 }
432 
433 u_int
434 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
435 {
436 	const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
437 	u_int usec;
438 
439 	/* NB: ah_curchan may be null when called attach time */
440 	if (c != AH_NULL) {
441 		usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
442 		if (IEEE80211_IS_CHAN_HT40(c))
443 			usec >>= 1;
444 	} else
445 		usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
446 	return usec;
447 }
448 
449 /*
450  * Setup a h/w rate table's reverse lookup table and
451  * fill in ack durations.  This routine is called for
452  * each rate table returned through the ah_getRateTable
453  * method.  The reverse lookup tables are assumed to be
454  * initialized to zero (or at least the first entry).
455  * We use this as a key that indicates whether or not
456  * we've previously setup the reverse lookup table.
457  *
458  * XXX not reentrant, but shouldn't matter
459  */
460 void
461 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
462 {
463 #define	N(a)	(sizeof(a)/sizeof(a[0]))
464 	int i;
465 
466 	if (rt->rateCodeToIndex[0] != 0)	/* already setup */
467 		return;
468 	for (i = 0; i < N(rt->rateCodeToIndex); i++)
469 		rt->rateCodeToIndex[i] = (uint8_t) -1;
470 	for (i = 0; i < rt->rateCount; i++) {
471 		uint8_t code = rt->info[i].rateCode;
472 		uint8_t cix = rt->info[i].controlRate;
473 
474 		HALASSERT(code < N(rt->rateCodeToIndex));
475 		rt->rateCodeToIndex[code] = i;
476 		HALASSERT((code | rt->info[i].shortPreamble) <
477 		    N(rt->rateCodeToIndex));
478 		rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
479 		/*
480 		 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
481 		 *     depends on whether they are marked as basic rates;
482 		 *     the static tables are setup with an 11b-compatible
483 		 *     2Mb/s rate which will work but is suboptimal
484 		 */
485 		rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
486 			WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
487 		rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
488 			WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
489 	}
490 #undef N
491 }
492 
493 HAL_STATUS
494 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
495 	uint32_t capability, uint32_t *result)
496 {
497 	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
498 
499 	switch (type) {
500 	case HAL_CAP_REG_DMN:		/* regulatory domain */
501 		*result = AH_PRIVATE(ah)->ah_currentRD;
502 		return HAL_OK;
503 	case HAL_CAP_CIPHER:		/* cipher handled in hardware */
504 	case HAL_CAP_TKIP_MIC:		/* handle TKIP MIC in hardware */
505 		return HAL_ENOTSUPP;
506 	case HAL_CAP_TKIP_SPLIT:	/* hardware TKIP uses split keys */
507 		return HAL_ENOTSUPP;
508 	case HAL_CAP_PHYCOUNTERS:	/* hardware PHY error counters */
509 		return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
510 	case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
511 		return HAL_ENOTSUPP;
512 	case HAL_CAP_DIVERSITY:		/* hardware supports fast diversity */
513 		return HAL_ENOTSUPP;
514 	case HAL_CAP_KEYCACHE_SIZE:	/* hardware key cache size */
515 		*result =  pCap->halKeyCacheSize;
516 		return HAL_OK;
517 	case HAL_CAP_NUM_TXQUEUES:	/* number of hardware tx queues */
518 		*result = pCap->halTotalQueues;
519 		return HAL_OK;
520 	case HAL_CAP_VEOL:		/* hardware supports virtual EOL */
521 		return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
522 	case HAL_CAP_PSPOLL:		/* hardware PS-Poll support works */
523 		return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
524 	case HAL_CAP_COMPRESSION:
525 		return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
526 	case HAL_CAP_BURST:
527 		return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
528 	case HAL_CAP_FASTFRAME:
529 		return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
530 	case HAL_CAP_DIAG:		/* hardware diagnostic support */
531 		*result = AH_PRIVATE(ah)->ah_diagreg;
532 		return HAL_OK;
533 	case HAL_CAP_TXPOW:		/* global tx power limit  */
534 		switch (capability) {
535 		case 0:			/* facility is supported */
536 			return HAL_OK;
537 		case 1:			/* current limit */
538 			*result = AH_PRIVATE(ah)->ah_powerLimit;
539 			return HAL_OK;
540 		case 2:			/* current max tx power */
541 			*result = AH_PRIVATE(ah)->ah_maxPowerLevel;
542 			return HAL_OK;
543 		case 3:			/* scale factor */
544 			*result = AH_PRIVATE(ah)->ah_tpScale;
545 			return HAL_OK;
546 		}
547 		return HAL_ENOTSUPP;
548 	case HAL_CAP_BSSIDMASK:		/* hardware supports bssid mask */
549 		return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
550 	case HAL_CAP_MCAST_KEYSRCH:	/* multicast frame keycache search */
551 		return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
552 	case HAL_CAP_TSF_ADJUST:	/* hardware has beacon tsf adjust */
553 		return HAL_ENOTSUPP;
554 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
555 		switch (capability) {
556 		case 0:			/* facility is supported */
557 			return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
558 		case 1:			/* current setting */
559 			return AH_PRIVATE(ah)->ah_rfkillEnabled ?
560 				HAL_OK : HAL_ENOTSUPP;
561 		case 2:			/* rfsilent config */
562 			*result = AH_PRIVATE(ah)->ah_rfsilent;
563 			return HAL_OK;
564 		}
565 		return HAL_ENOTSUPP;
566 	case HAL_CAP_11D:
567 		return HAL_OK;
568 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
569 		return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
570 	case HAL_CAP_HT:
571 		return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
572 	case HAL_CAP_TX_CHAINMASK:	/* mask of TX chains supported */
573 		*result = pCap->halTxChainMask;
574 		return HAL_OK;
575 	case HAL_CAP_RX_CHAINMASK:	/* mask of RX chains supported */
576 		*result = pCap->halRxChainMask;
577 		return HAL_OK;
578 	case HAL_CAP_RXTSTAMP_PREC:	/* rx desc tstamp precision (bits) */
579 		*result = pCap->halTstampPrecision;
580 		return HAL_OK;
581 	case HAL_CAP_INTRMASK:		/* mask of supported interrupts */
582 		*result = pCap->halIntrMask;
583 		return HAL_OK;
584 	case HAL_CAP_BSSIDMATCH:	/* hardware has disable bssid match */
585 		return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
586 	default:
587 		return HAL_EINVAL;
588 	}
589 }
590 
591 HAL_BOOL
592 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
593 	uint32_t capability, uint32_t setting, HAL_STATUS *status)
594 {
595 
596 	switch (type) {
597 	case HAL_CAP_TXPOW:
598 		switch (capability) {
599 		case 3:
600 			if (setting <= HAL_TP_SCALE_MIN) {
601 				AH_PRIVATE(ah)->ah_tpScale = setting;
602 				return AH_TRUE;
603 			}
604 			break;
605 		}
606 		break;
607 	case HAL_CAP_RFSILENT:		/* rfsilent support  */
608 		/*
609 		 * NB: allow even if halRfSilentSupport is false
610 		 *     in case the EEPROM is misprogrammed.
611 		 */
612 		switch (capability) {
613 		case 1:			/* current setting */
614 			AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
615 			return AH_TRUE;
616 		case 2:			/* rfsilent config */
617 			/* XXX better done per-chip for validation? */
618 			AH_PRIVATE(ah)->ah_rfsilent = setting;
619 			return AH_TRUE;
620 		}
621 		break;
622 	case HAL_CAP_REG_DMN:		/* regulatory domain */
623 		AH_PRIVATE(ah)->ah_currentRD = setting;
624 		return AH_TRUE;
625 	case HAL_CAP_RXORN_FATAL:	/* HAL_INT_RXORN treated as fatal  */
626 		AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
627 		return AH_TRUE;
628 	default:
629 		break;
630 	}
631 	if (status)
632 		*status = HAL_EINVAL;
633 	return AH_FALSE;
634 }
635 
636 /*
637  * Common support for getDiagState method.
638  */
639 
640 static u_int
641 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
642 	void *dstbuf, int space)
643 {
644 	uint32_t *dp = dstbuf;
645 	int i;
646 
647 	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
648 		u_int r = regs[i].start;
649 		u_int e = regs[i].end;
650 		*dp++ = (r<<16) | e;
651 		space -= sizeof(uint32_t);
652 		do {
653 			*dp++ = OS_REG_READ(ah, r);
654 			r += sizeof(uint32_t);
655 			space -= sizeof(uint32_t);
656 		} while (r <= e && space >= sizeof(uint32_t));
657 	}
658 	return (char *) dp - (char *) dstbuf;
659 }
660 
661 static void
662 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
663 {
664 	while (space >= sizeof(HAL_REGWRITE)) {
665 		OS_REG_WRITE(ah, regs->addr, regs->value);
666 		regs++, space -= sizeof(HAL_REGWRITE);
667 	}
668 }
669 
670 HAL_BOOL
671 ath_hal_getdiagstate(struct ath_hal *ah, int request,
672 	const void *args, uint32_t argsize,
673 	void **result, uint32_t *resultsize)
674 {
675 	switch (request) {
676 	case HAL_DIAG_REVS:
677 		*result = &AH_PRIVATE(ah)->ah_devid;
678 		*resultsize = sizeof(HAL_REVS);
679 		return AH_TRUE;
680 	case HAL_DIAG_REGS:
681 		*resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
682 		return AH_TRUE;
683 	case HAL_DIAG_SETREGS:
684 		ath_hal_setregs(ah, args, argsize);
685 		*resultsize = 0;
686 		return AH_TRUE;
687 	case HAL_DIAG_FATALERR:
688 		*result = &AH_PRIVATE(ah)->ah_fatalState[0];
689 		*resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
690 		return AH_TRUE;
691 	case HAL_DIAG_EEREAD:
692 		if (argsize != sizeof(uint16_t))
693 			return AH_FALSE;
694 		if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
695 			return AH_FALSE;
696 		*resultsize = sizeof(uint16_t);
697 		return AH_TRUE;
698 #ifdef AH_PRIVATE_DIAG
699 	case HAL_DIAG_SETKEY: {
700 		const HAL_DIAG_KEYVAL *dk;
701 
702 		if (argsize != sizeof(HAL_DIAG_KEYVAL))
703 			return AH_FALSE;
704 		dk = (const HAL_DIAG_KEYVAL *)args;
705 		return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
706 			&dk->dk_keyval, dk->dk_mac, dk->dk_xor);
707 	}
708 	case HAL_DIAG_RESETKEY:
709 		if (argsize != sizeof(uint16_t))
710 			return AH_FALSE;
711 		return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
712 #ifdef AH_SUPPORT_WRITE_EEPROM
713 	case HAL_DIAG_EEWRITE: {
714 		const HAL_DIAG_EEVAL *ee;
715 		if (argsize != sizeof(HAL_DIAG_EEVAL))
716 			return AH_FALSE;
717 		ee = (const HAL_DIAG_EEVAL *)args;
718 		return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
719 	}
720 #endif /* AH_SUPPORT_WRITE_EEPROM */
721 #endif /* AH_PRIVATE_DIAG */
722 	case HAL_DIAG_11NCOMPAT:
723 		if (argsize == 0) {
724 			*resultsize = sizeof(uint32_t);
725 			*((uint32_t *)(*result)) =
726 				AH_PRIVATE(ah)->ah_11nCompat;
727 		} else if (argsize == sizeof(uint32_t)) {
728 			AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
729 		} else
730 			return AH_FALSE;
731 		return AH_TRUE;
732 	}
733 	return AH_FALSE;
734 }
735 
736 /*
737  * Set the properties of the tx queue with the parameters
738  * from qInfo.
739  */
740 HAL_BOOL
741 ath_hal_setTxQProps(struct ath_hal *ah,
742 	HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
743 {
744 	uint32_t cw;
745 
746 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
747 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
748 		    "%s: inactive queue\n", __func__);
749 		return AH_FALSE;
750 	}
751 	/* XXX validate parameters */
752 	qi->tqi_ver = qInfo->tqi_ver;
753 	qi->tqi_subtype = qInfo->tqi_subtype;
754 	qi->tqi_qflags = qInfo->tqi_qflags;
755 	qi->tqi_priority = qInfo->tqi_priority;
756 	if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
757 		qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
758 	else
759 		qi->tqi_aifs = INIT_AIFS;
760 	if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
761 		cw = AH_MIN(qInfo->tqi_cwmin, 1024);
762 		/* make sure that the CWmin is of the form (2^n - 1) */
763 		qi->tqi_cwmin = 1;
764 		while (qi->tqi_cwmin < cw)
765 			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
766 	} else
767 		qi->tqi_cwmin = qInfo->tqi_cwmin;
768 	if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
769 		cw = AH_MIN(qInfo->tqi_cwmax, 1024);
770 		/* make sure that the CWmax is of the form (2^n - 1) */
771 		qi->tqi_cwmax = 1;
772 		while (qi->tqi_cwmax < cw)
773 			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
774 	} else
775 		qi->tqi_cwmax = INIT_CWMAX;
776 	/* Set retry limit values */
777 	if (qInfo->tqi_shretry != 0)
778 		qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
779 	else
780 		qi->tqi_shretry = INIT_SH_RETRY;
781 	if (qInfo->tqi_lgretry != 0)
782 		qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
783 	else
784 		qi->tqi_lgretry = INIT_LG_RETRY;
785 	qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
786 	qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
787 	qi->tqi_burstTime = qInfo->tqi_burstTime;
788 	qi->tqi_readyTime = qInfo->tqi_readyTime;
789 
790 	switch (qInfo->tqi_subtype) {
791 	case HAL_WME_UPSD:
792 		if (qi->tqi_type == HAL_TX_QUEUE_DATA)
793 			qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
794 		break;
795 	default:
796 		break;		/* NB: silence compiler */
797 	}
798 	return AH_TRUE;
799 }
800 
801 HAL_BOOL
802 ath_hal_getTxQProps(struct ath_hal *ah,
803 	HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
804 {
805 	if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
806 		HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
807 		    "%s: inactive queue\n", __func__);
808 		return AH_FALSE;
809 	}
810 
811 	qInfo->tqi_qflags = qi->tqi_qflags;
812 	qInfo->tqi_ver = qi->tqi_ver;
813 	qInfo->tqi_subtype = qi->tqi_subtype;
814 	qInfo->tqi_qflags = qi->tqi_qflags;
815 	qInfo->tqi_priority = qi->tqi_priority;
816 	qInfo->tqi_aifs = qi->tqi_aifs;
817 	qInfo->tqi_cwmin = qi->tqi_cwmin;
818 	qInfo->tqi_cwmax = qi->tqi_cwmax;
819 	qInfo->tqi_shretry = qi->tqi_shretry;
820 	qInfo->tqi_lgretry = qi->tqi_lgretry;
821 	qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
822 	qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
823 	qInfo->tqi_burstTime = qi->tqi_burstTime;
824 	qInfo->tqi_readyTime = qi->tqi_readyTime;
825 	return AH_TRUE;
826 }
827 
828                                      /* 11a Turbo  11b  11g  108g */
829 static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
830 
831 /*
832  * Read the current channel noise floor and return.
833  * If nf cal hasn't finished, channel noise floor should be 0
834  * and we return a nominal value based on band and frequency.
835  *
836  * NB: This is a private routine used by per-chip code to
837  *     implement the ah_getChanNoise method.
838  */
839 int16_t
840 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
841 {
842 	HAL_CHANNEL_INTERNAL *ichan;
843 
844 	ichan = ath_hal_checkchannel(ah, chan);
845 	if (ichan == AH_NULL) {
846 		HALDEBUG(ah, HAL_DEBUG_NFCAL,
847 		    "%s: invalid channel %u/0x%x; no mapping\n",
848 		    __func__, chan->ic_freq, chan->ic_flags);
849 		return 0;
850 	}
851 	if (ichan->rawNoiseFloor == 0) {
852 		WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
853 
854 		HALASSERT(mode < WIRELESS_MODE_MAX);
855 		return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
856 	} else
857 		return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
858 }
859 
860 /*
861  * Process all valid raw noise floors into the dBm noise floor values.
862  * Though our device has no reference for a dBm noise floor, we perform
863  * a relative minimization of NF's based on the lowest NF found across a
864  * channel scan.
865  */
866 void
867 ath_hal_process_noisefloor(struct ath_hal *ah)
868 {
869 	HAL_CHANNEL_INTERNAL *c;
870 	int16_t correct2, correct5;
871 	int16_t lowest2, lowest5;
872 	int i;
873 
874 	/*
875 	 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
876 	 * for statistically recorded NF/channel deviation.
877 	 */
878 	correct2 = lowest2 = 0;
879 	correct5 = lowest5 = 0;
880 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
881 		WIRELESS_MODE mode;
882 		int16_t nf;
883 
884 		c = &AH_PRIVATE(ah)->ah_channels[i];
885 		if (c->rawNoiseFloor >= 0)
886 			continue;
887 		/* XXX can't identify proper mode */
888 		mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
889 		nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
890 			ath_hal_getNfAdjust(ah, c);
891 		if (IS_CHAN_5GHZ(c)) {
892 			if (nf < lowest5) {
893 				lowest5 = nf;
894 				correct5 = NOISE_FLOOR[mode] -
895 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
896 			}
897 		} else {
898 			if (nf < lowest2) {
899 				lowest2 = nf;
900 				correct2 = NOISE_FLOOR[mode] -
901 				    (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
902 			}
903 		}
904 	}
905 
906 	/* Correct the channels to reach the expected NF value */
907 	for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
908 		c = &AH_PRIVATE(ah)->ah_channels[i];
909 		if (c->rawNoiseFloor >= 0)
910 			continue;
911 		/* Apply correction factor */
912 		c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
913 			(IS_CHAN_5GHZ(c) ? correct5 : correct2);
914 		HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
915 		    c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
916 	}
917 }
918 
919 /*
920  * INI support routines.
921  */
922 
923 int
924 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
925 	int col, int regWr)
926 {
927 	int r;
928 
929 	HALASSERT(col < ia->cols);
930 	for (r = 0; r < ia->rows; r++) {
931 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
932 		    HAL_INI_VAL(ia, r, col));
933 
934 		/* Analog shift register delay seems needed for Merlin - PR kern/154220 */
935 		if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x78a0)
936 			OS_DELAY(100);
937 
938 		DMA_YIELD(regWr);
939 	}
940 	return regWr;
941 }
942 
943 void
944 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
945 {
946 	int r;
947 
948 	HALASSERT(col < ia->cols);
949 	for (r = 0; r < ia->rows; r++)
950 		data[r] = HAL_INI_VAL(ia, r, col);
951 }
952 
953 int
954 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
955 	const uint32_t data[], int regWr)
956 {
957 	int r;
958 
959 	for (r = 0; r < ia->rows; r++) {
960 		OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
961 
962 		/* Analog shift register delay seems needed for Merlin - PR kern/154220 */
963 		/* XXX verify whether any analog radio bank writes will hit up this */
964 		/* XXX since this is a merlin work-around; and merlin doesn't use radio banks */
965 		if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x78a0)
966 			OS_DELAY(100);
967 		DMA_YIELD(regWr);
968 	}
969 	return regWr;
970 }
971