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