2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
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.
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.
22 #include "ah_internal.h"
24 #include "ah_eeprom.h" /* for 5ghz fast clock flag */
26 #include "ar5416/ar5416reg.h" /* NB: includes ar5212reg.h */
27 #include "ar9003/ar9300_devid.h"
29 /* linker set of registered chips */
30 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
33 * Check the set of registered chips to see if any recognize
34 * the device as one they can support.
37 ath_hal_probe(uint16_t vendorid, uint16_t devid)
39 struct ath_hal_chip * const *pchip;
41 OS_SET_FOREACH(pchip, ah_chips) {
42 const char *name = (*pchip)->probe(vendorid, devid);
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
57 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
58 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
59 HAL_OPS_CONFIG *ah_config,
62 struct ath_hal_chip * const *pchip;
64 OS_SET_FOREACH(pchip, ah_chips) {
65 struct ath_hal_chip *chip = *pchip;
68 /* XXX don't have vendorid, assume atheros one works */
69 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
71 ah = chip->attach(devid, sc, st, sh, eepromdata, ah_config,
74 /* copy back private state to public area */
75 ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
76 ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
77 ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
78 ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
79 ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
80 ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
81 ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
89 ath_hal_mac_name(struct ath_hal *ah)
91 switch (ah->ah_macVersion) {
92 case AR_SREV_VERSION_CRETE:
93 case AR_SREV_VERSION_MAUI_1:
95 case AR_SREV_VERSION_MAUI_2:
96 case AR_SREV_VERSION_OAHU:
98 case AR_SREV_VERSION_VENICE:
100 case AR_SREV_VERSION_GRIFFIN:
102 case AR_SREV_VERSION_CONDOR:
104 case AR_SREV_VERSION_EAGLE:
106 case AR_SREV_VERSION_COBRA:
108 case AR_SREV_2425: /* Swan */
110 case AR_SREV_2417: /* Nala */
112 case AR_XSREV_VERSION_OWL_PCI:
114 case AR_XSREV_VERSION_OWL_PCIE:
116 case AR_XSREV_VERSION_HOWL:
118 case AR_XSREV_VERSION_SOWL:
120 case AR_XSREV_VERSION_MERLIN:
121 if (AH_PRIVATE(ah)->ah_ispcie)
124 case AR_XSREV_VERSION_KITE:
126 case AR_XSREV_VERSION_KIWI:
127 if (AH_PRIVATE(ah)->ah_ispcie)
130 case AR_SREV_VERSION_AR9380:
131 if (ah->ah_macRev >= AR_SREV_REVISION_AR9580_10)
134 case AR_SREV_VERSION_AR9460:
136 case AR_SREV_VERSION_AR9330:
138 case AR_SREV_VERSION_AR9340:
140 case AR_SREV_VERSION_QCA9550:
142 case AR_SREV_VERSION_AR9485:
144 case AR_SREV_VERSION_QCA9565:
146 case AR_SREV_VERSION_QCA9530:
153 * Return the mask of available modes based on the hardware capabilities.
156 ath_hal_getwirelessmodes(struct ath_hal*ah)
158 return ath_hal_getWirelessModes(ah);
161 /* linker set of registered RF backends */
162 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
165 * Check the set of registered RF backends to see if
166 * any recognize the device as one they can support.
169 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
171 struct ath_hal_rf * const *prf;
173 OS_SET_FOREACH(prf, ah_rfs) {
174 struct ath_hal_rf *rf = *prf;
178 *ecode = HAL_ENOTSUPP;
183 ath_hal_rf_name(struct ath_hal *ah)
185 switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
187 return "5110"; /* NB: made up */
188 case AR_RAD5111_SREV_MAJOR:
189 case AR_RAD5111_SREV_PROD:
191 case AR_RAD2111_SREV_MAJOR:
193 case AR_RAD5112_SREV_MAJOR:
194 case AR_RAD5112_SREV_2_0:
195 case AR_RAD5112_SREV_2_1:
197 case AR_RAD2112_SREV_MAJOR:
198 case AR_RAD2112_SREV_2_0:
199 case AR_RAD2112_SREV_2_1:
201 case AR_RAD2413_SREV_MAJOR:
203 case AR_RAD5413_SREV_MAJOR:
205 case AR_RAD2316_SREV_MAJOR:
207 case AR_RAD2317_SREV_MAJOR:
209 case AR_RAD5424_SREV_MAJOR:
212 case AR_RAD5133_SREV_MAJOR:
214 case AR_RAD2133_SREV_MAJOR:
216 case AR_RAD5122_SREV_MAJOR:
218 case AR_RAD2122_SREV_MAJOR:
225 * Poll the register looking for a specific value.
228 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
230 #define AH_TIMEOUT 1000
231 return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
236 ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
240 for (i = 0; i < timeout; i++) {
241 if ((OS_REG_READ(ah, reg) & mask) == val)
245 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
246 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
247 __func__, reg, OS_REG_READ(ah, reg), mask, val);
252 * Reverse the bits starting at the low bit for a value of
256 ath_hal_reverseBits(uint32_t val, uint32_t n)
261 for (i = 0, retval = 0; i < n; i++) {
262 retval = (retval << 1) | (val & 1);
268 /* 802.11n related timing definitions */
270 #define OFDM_PLCP_BITS 22
276 #define HT_LTF(n) ((n) * 4)
278 #define HT_RC_2_MCS(_rc) ((_rc) & 0xf)
279 #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
280 #define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS)
283 * Calculate the duration of a packet whether it is 11n or legacy.
286 ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
287 uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
292 rc = rates->info[rateix].rateCode;
294 /* Legacy rate? Return the old way */
295 if (! IS_HT_RATE(rc))
296 return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
298 /* 11n frame - extract out the number of spatial streams */
299 numStreams = HT_RC_2_STREAMS(rc);
300 KASSERT(numStreams > 0 && numStreams <= 4,
301 ("number of spatial streams needs to be 1..3: MCS rate 0x%x!",
304 return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
307 static const uint16_t ht20_bps[32] = {
308 26, 52, 78, 104, 156, 208, 234, 260,
309 52, 104, 156, 208, 312, 416, 468, 520,
310 78, 156, 234, 312, 468, 624, 702, 780,
311 104, 208, 312, 416, 624, 832, 936, 1040
313 static const uint16_t ht40_bps[32] = {
314 54, 108, 162, 216, 324, 432, 486, 540,
315 108, 216, 324, 432, 648, 864, 972, 1080,
316 162, 324, 486, 648, 972, 1296, 1458, 1620,
317 216, 432, 648, 864, 1296, 1728, 1944, 2160
321 * Calculate the transmit duration of an 11n frame.
324 ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams,
325 HAL_BOOL isht40, HAL_BOOL isShortGI)
327 uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
329 KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
330 KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate));
333 bitsPerSymbol = ht40_bps[rate & 0x1f];
335 bitsPerSymbol = ht20_bps[rate & 0x1f];
336 numBits = OFDM_PLCP_BITS + (frameLen << 3);
337 numSymbols = howmany(numBits, bitsPerSymbol);
339 txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */
341 txTime = numSymbols * 4; /* 4us */
342 return txTime + HT_L_STF + HT_L_LTF +
343 HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
347 * Compute the time to transmit a frame of length frameLen bytes
348 * using the specified rate, phy, and short preamble setting.
351 ath_hal_computetxtime(struct ath_hal *ah,
352 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
353 HAL_BOOL shortPreamble)
355 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
358 /* Warn if this function is called for 11n rates; it should not be! */
359 if (IS_HT_RATE(rates->info[rateix].rateCode))
360 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
361 __func__, rateix, rates->info[rateix].rateCode);
363 kbps = rates->info[rateix].rateKbps;
365 * index can be invalid during dynamic Turbo transitions.
370 switch (rates->info[rateix].phy) {
371 case IEEE80211_T_CCK:
372 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
373 if (shortPreamble && rates->info[rateix].shortPreamble)
375 numBits = frameLen << 3;
376 txTime = CCK_SIFS_TIME + phyTime
377 + ((numBits * 1000)/kbps);
379 case IEEE80211_T_OFDM:
380 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
381 HALASSERT(bitsPerSymbol != 0);
383 numBits = OFDM_PLCP_BITS + (frameLen << 3);
384 numSymbols = howmany(numBits, bitsPerSymbol);
385 txTime = OFDM_SIFS_TIME
387 + (numSymbols * OFDM_SYMBOL_TIME);
389 case IEEE80211_T_OFDM_HALF:
390 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
391 HALASSERT(bitsPerSymbol != 0);
393 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3);
394 numSymbols = howmany(numBits, bitsPerSymbol);
395 txTime = OFDM_HALF_SIFS_TIME
396 + OFDM_HALF_PREAMBLE_TIME
397 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
399 case IEEE80211_T_OFDM_QUARTER:
400 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
401 HALASSERT(bitsPerSymbol != 0);
403 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
404 numSymbols = howmany(numBits, bitsPerSymbol);
405 txTime = OFDM_QUARTER_SIFS_TIME
406 + OFDM_QUARTER_PREAMBLE_TIME
407 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
409 case IEEE80211_T_TURBO:
410 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000;
411 HALASSERT(bitsPerSymbol != 0);
413 numBits = TURBO_PLCP_BITS + (frameLen << 3);
414 numSymbols = howmany(numBits, bitsPerSymbol);
415 txTime = TURBO_SIFS_TIME
416 + TURBO_PREAMBLE_TIME
417 + (numSymbols * TURBO_SYMBOL_TIME);
420 HALDEBUG(ah, HAL_DEBUG_PHYIO,
421 "%s: unknown phy %u (rate ix %u)\n",
422 __func__, rates->info[rateix].phy, rateix);
430 ath_hal_get_curmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
433 * Pick a default mode at bootup. A channel change is inevitable.
436 return HAL_MODE_11NG_HT20;
438 if (IEEE80211_IS_CHAN_TURBO(chan))
439 return HAL_MODE_TURBO;
441 /* check for NA_HT before plain A, since IS_CHAN_A includes NA_HT */
442 if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
443 return HAL_MODE_11NA_HT20;
444 if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
445 return HAL_MODE_11NA_HT40PLUS;
446 if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
447 return HAL_MODE_11NA_HT40MINUS;
448 if (IEEE80211_IS_CHAN_A(chan))
451 /* check for NG_HT before plain G, since IS_CHAN_G includes NG_HT */
452 if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
453 return HAL_MODE_11NG_HT20;
454 if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
455 return HAL_MODE_11NG_HT40PLUS;
456 if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
457 return HAL_MODE_11NG_HT40MINUS;
460 * XXX For FreeBSD, will this work correctly given the DYN
461 * chan mode (OFDM+CCK dynamic) ? We have pure-G versions DYN-BG..
463 if (IEEE80211_IS_CHAN_G(chan))
465 if (IEEE80211_IS_CHAN_B(chan))
469 return HAL_MODE_11NG_HT20;
474 WIRELESS_MODE_11a = 0,
475 WIRELESS_MODE_TURBO = 1,
476 WIRELESS_MODE_11b = 2,
477 WIRELESS_MODE_11g = 3,
478 WIRELESS_MODE_108g = 4,
484 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
486 if (IEEE80211_IS_CHAN_B(chan))
487 return WIRELESS_MODE_11b;
488 if (IEEE80211_IS_CHAN_G(chan))
489 return WIRELESS_MODE_11g;
490 if (IEEE80211_IS_CHAN_108G(chan))
491 return WIRELESS_MODE_108g;
492 if (IEEE80211_IS_CHAN_TURBO(chan))
493 return WIRELESS_MODE_TURBO;
494 return WIRELESS_MODE_11a;
498 * Convert between microseconds and core system clocks.
500 /* 11a Turbo 11b 11g 108g */
501 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
503 #define CLOCK_FAST_RATE_5GHZ_OFDM 44
506 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
508 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
511 /* NB: ah_curchan may be null when called attach time */
512 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
513 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
514 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
515 if (IEEE80211_IS_CHAN_HT40(c))
517 } else if (c != AH_NULL) {
518 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
519 if (IEEE80211_IS_CHAN_HT40(c))
522 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
524 /* Compensate for half/quarter rate */
525 if (c != AH_NULL && IEEE80211_IS_CHAN_HALF(c))
527 else if (c != AH_NULL && IEEE80211_IS_CHAN_QUARTER(c))
534 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
536 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
539 /* NB: ah_curchan may be null when called attach time */
540 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
541 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
542 usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
543 if (IEEE80211_IS_CHAN_HT40(c))
545 } else if (c != AH_NULL) {
546 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
547 if (IEEE80211_IS_CHAN_HT40(c))
550 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
555 * Setup a h/w rate table's reverse lookup table and
556 * fill in ack durations. This routine is called for
557 * each rate table returned through the ah_getRateTable
558 * method. The reverse lookup tables are assumed to be
559 * initialized to zero (or at least the first entry).
560 * We use this as a key that indicates whether or not
561 * we've previously setup the reverse lookup table.
563 * XXX not reentrant, but shouldn't matter
566 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
568 #define N(a) (sizeof(a)/sizeof(a[0]))
571 if (rt->rateCodeToIndex[0] != 0) /* already setup */
573 for (i = 0; i < N(rt->rateCodeToIndex); i++)
574 rt->rateCodeToIndex[i] = (uint8_t) -1;
575 for (i = 0; i < rt->rateCount; i++) {
576 uint8_t code = rt->info[i].rateCode;
577 uint8_t cix = rt->info[i].controlRate;
579 HALASSERT(code < N(rt->rateCodeToIndex));
580 rt->rateCodeToIndex[code] = i;
581 HALASSERT((code | rt->info[i].shortPreamble) <
582 N(rt->rateCodeToIndex));
583 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
585 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
586 * depends on whether they are marked as basic rates;
587 * the static tables are setup with an 11b-compatible
588 * 2Mb/s rate which will work but is suboptimal
590 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
591 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
592 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
593 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
599 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
600 uint32_t capability, uint32_t *result)
602 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
605 case HAL_CAP_REG_DMN: /* regulatory domain */
606 *result = AH_PRIVATE(ah)->ah_currentRD;
608 case HAL_CAP_DFS_DMN: /* DFS Domain */
609 *result = AH_PRIVATE(ah)->ah_dfsDomain;
611 case HAL_CAP_CIPHER: /* cipher handled in hardware */
612 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
614 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
616 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
617 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
618 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
620 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
622 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
623 *result = pCap->halKeyCacheSize;
625 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
626 *result = pCap->halTotalQueues;
628 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
629 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
630 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
631 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
632 case HAL_CAP_COMPRESSION:
633 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
635 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
636 case HAL_CAP_FASTFRAME:
637 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
638 case HAL_CAP_DIAG: /* hardware diagnostic support */
639 *result = AH_PRIVATE(ah)->ah_diagreg;
641 case HAL_CAP_TXPOW: /* global tx power limit */
642 switch (capability) {
643 case 0: /* facility is supported */
645 case 1: /* current limit */
646 *result = AH_PRIVATE(ah)->ah_powerLimit;
648 case 2: /* current max tx power */
649 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
651 case 3: /* scale factor */
652 *result = AH_PRIVATE(ah)->ah_tpScale;
656 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
657 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
658 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
659 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
660 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
662 case HAL_CAP_RFSILENT: /* rfsilent support */
663 switch (capability) {
664 case 0: /* facility is supported */
665 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
666 case 1: /* current setting */
667 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
668 HAL_OK : HAL_ENOTSUPP;
669 case 2: /* rfsilent config */
670 *result = AH_PRIVATE(ah)->ah_rfsilent;
678 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
680 return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
681 case HAL_CAP_FAST_CC:
682 return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
683 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
684 *result = pCap->halTxChainMask;
686 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
687 *result = pCap->halRxChainMask;
689 case HAL_CAP_NUM_GPIO_PINS:
690 *result = pCap->halNumGpioPins;
693 return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
694 case HAL_CAP_RTS_AGGR_LIMIT:
695 *result = pCap->halRtsAggrLimit;
697 case HAL_CAP_4ADDR_AGGR:
698 return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
699 case HAL_CAP_EXT_CHAN_DFS:
700 return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
701 case HAL_CAP_RX_STBC:
702 return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
703 case HAL_CAP_TX_STBC:
704 return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
705 case HAL_CAP_COMBINED_RADAR_RSSI:
706 return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
707 case HAL_CAP_AUTO_SLEEP:
708 return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
709 case HAL_CAP_MBSSID_AGGR_SUPPORT:
710 return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
711 case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */
712 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
713 case HAL_CAP_REG_FLAG:
714 *result = AH_PRIVATE(ah)->ah_currentRDext;
716 case HAL_CAP_ENHANCED_DMA_SUPPORT:
717 return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP;
718 case HAL_CAP_NUM_TXMAPS:
719 *result = pCap->halNumTxMaps;
721 case HAL_CAP_TXDESCLEN:
722 *result = pCap->halTxDescLen;
724 case HAL_CAP_TXSTATUSLEN:
725 *result = pCap->halTxStatusLen;
727 case HAL_CAP_RXSTATUSLEN:
728 *result = pCap->halRxStatusLen;
730 case HAL_CAP_RXFIFODEPTH:
731 switch (capability) {
732 case HAL_RX_QUEUE_HP:
733 *result = pCap->halRxHpFifoDepth;
735 case HAL_RX_QUEUE_LP:
736 *result = pCap->halRxLpFifoDepth;
741 case HAL_CAP_RXBUFSIZE:
742 case HAL_CAP_NUM_MR_RETRIES:
743 *result = pCap->halNumMRRetries;
745 case HAL_CAP_BT_COEX:
746 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
747 case HAL_CAP_SPECTRAL_SCAN:
748 return pCap->halSpectralScanSupport ? HAL_OK : HAL_ENOTSUPP;
749 case HAL_CAP_HT20_SGI:
750 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
751 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
752 *result = pCap->halTstampPrecision;
754 case HAL_CAP_ANT_DIV_COMB: /* AR9285/AR9485 LNA diversity */
755 return pCap->halAntDivCombSupport ? HAL_OK : HAL_ENOTSUPP;
757 case HAL_CAP_ENHANCED_DFS_SUPPORT:
758 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
760 /* FreeBSD-specific entries for now */
761 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
762 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
763 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
764 *result = pCap->halIntrMask;
766 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
767 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
768 case HAL_CAP_STREAMS: /* number of 11n spatial streams */
769 switch (capability) {
771 *result = pCap->halTxStreams;
774 *result = pCap->halRxStreams;
779 case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */
780 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
781 case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */
782 return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP;
783 case HAL_CAP_BB_READ_WAR: /* Baseband read WAR */
784 return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP;
785 case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */
786 return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP;
787 case HAL_CAP_MFP: /* Management frame protection setting */
788 *result = pCap->halMfpSupport;
790 case HAL_CAP_RX_LNA_MIXING: /* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */
791 return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP;
792 case HAL_CAP_DO_MYBEACON: /* Hardware supports filtering my-beacons */
793 return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP;
800 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
801 uint32_t capability, uint32_t setting, HAL_STATUS *status)
806 switch (capability) {
808 if (setting <= HAL_TP_SCALE_MIN) {
809 AH_PRIVATE(ah)->ah_tpScale = setting;
815 case HAL_CAP_RFSILENT: /* rfsilent support */
817 * NB: allow even if halRfSilentSupport is false
818 * in case the EEPROM is misprogrammed.
820 switch (capability) {
821 case 1: /* current setting */
822 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
824 case 2: /* rfsilent config */
825 /* XXX better done per-chip for validation? */
826 AH_PRIVATE(ah)->ah_rfsilent = setting;
830 case HAL_CAP_REG_DMN: /* regulatory domain */
831 AH_PRIVATE(ah)->ah_currentRD = setting;
833 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
834 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
840 *status = HAL_EINVAL;
845 * Common support for getDiagState method.
849 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
850 void *dstbuf, int space)
852 uint32_t *dp = dstbuf;
855 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
856 uint32_t r = regs[i].start;
857 uint32_t e = regs[i].end;
860 space -= 2*sizeof(uint32_t);
862 *dp++ = OS_REG_READ(ah, r);
863 r += sizeof(uint32_t);
864 space -= sizeof(uint32_t);
865 } while (r <= e && space >= sizeof(uint32_t));
867 return (char *) dp - (char *) dstbuf;
871 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
873 while (space >= sizeof(HAL_REGWRITE)) {
874 OS_REG_WRITE(ah, regs->addr, regs->value);
875 regs++, space -= sizeof(HAL_REGWRITE);
880 ath_hal_getdiagstate(struct ath_hal *ah, int request,
881 const void *args, uint32_t argsize,
882 void **result, uint32_t *resultsize)
887 *result = &AH_PRIVATE(ah)->ah_devid;
888 *resultsize = sizeof(HAL_REVS);
891 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
893 case HAL_DIAG_SETREGS:
894 ath_hal_setregs(ah, args, argsize);
897 case HAL_DIAG_FATALERR:
898 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
899 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
901 case HAL_DIAG_EEREAD:
902 if (argsize != sizeof(uint16_t))
904 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
906 *resultsize = sizeof(uint16_t);
908 #ifdef AH_PRIVATE_DIAG
909 case HAL_DIAG_SETKEY: {
910 const HAL_DIAG_KEYVAL *dk;
912 if (argsize != sizeof(HAL_DIAG_KEYVAL))
914 dk = (const HAL_DIAG_KEYVAL *)args;
915 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
916 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
918 case HAL_DIAG_RESETKEY:
919 if (argsize != sizeof(uint16_t))
921 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
922 #ifdef AH_SUPPORT_WRITE_EEPROM
923 case HAL_DIAG_EEWRITE: {
924 const HAL_DIAG_EEVAL *ee;
925 if (argsize != sizeof(HAL_DIAG_EEVAL))
927 ee = (const HAL_DIAG_EEVAL *)args;
928 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
930 #endif /* AH_SUPPORT_WRITE_EEPROM */
931 #endif /* AH_PRIVATE_DIAG */
932 case HAL_DIAG_11NCOMPAT:
934 *resultsize = sizeof(uint32_t);
935 *((uint32_t *)(*result)) =
936 AH_PRIVATE(ah)->ah_11nCompat;
937 } else if (argsize == sizeof(uint32_t)) {
938 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
942 case HAL_DIAG_CHANSURVEY:
943 *result = &AH_PRIVATE(ah)->ah_chansurvey;
944 *resultsize = sizeof(HAL_CHANNEL_SURVEY);
951 * Set the properties of the tx queue with the parameters
955 ath_hal_setTxQProps(struct ath_hal *ah,
956 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
960 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
961 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
962 "%s: inactive queue\n", __func__);
965 /* XXX validate parameters */
966 qi->tqi_ver = qInfo->tqi_ver;
967 qi->tqi_subtype = qInfo->tqi_subtype;
968 qi->tqi_qflags = qInfo->tqi_qflags;
969 qi->tqi_priority = qInfo->tqi_priority;
970 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
971 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
973 qi->tqi_aifs = INIT_AIFS;
974 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
975 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
976 /* make sure that the CWmin is of the form (2^n - 1) */
978 while (qi->tqi_cwmin < cw)
979 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
981 qi->tqi_cwmin = qInfo->tqi_cwmin;
982 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
983 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
984 /* make sure that the CWmax is of the form (2^n - 1) */
986 while (qi->tqi_cwmax < cw)
987 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
989 qi->tqi_cwmax = INIT_CWMAX;
990 /* Set retry limit values */
991 if (qInfo->tqi_shretry != 0)
992 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
994 qi->tqi_shretry = INIT_SH_RETRY;
995 if (qInfo->tqi_lgretry != 0)
996 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
998 qi->tqi_lgretry = INIT_LG_RETRY;
999 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
1000 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
1001 qi->tqi_burstTime = qInfo->tqi_burstTime;
1002 qi->tqi_readyTime = qInfo->tqi_readyTime;
1004 switch (qInfo->tqi_subtype) {
1006 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
1007 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
1010 break; /* NB: silence compiler */
1016 ath_hal_getTxQProps(struct ath_hal *ah,
1017 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
1019 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
1020 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
1021 "%s: inactive queue\n", __func__);
1025 qInfo->tqi_qflags = qi->tqi_qflags;
1026 qInfo->tqi_ver = qi->tqi_ver;
1027 qInfo->tqi_subtype = qi->tqi_subtype;
1028 qInfo->tqi_qflags = qi->tqi_qflags;
1029 qInfo->tqi_priority = qi->tqi_priority;
1030 qInfo->tqi_aifs = qi->tqi_aifs;
1031 qInfo->tqi_cwmin = qi->tqi_cwmin;
1032 qInfo->tqi_cwmax = qi->tqi_cwmax;
1033 qInfo->tqi_shretry = qi->tqi_shretry;
1034 qInfo->tqi_lgretry = qi->tqi_lgretry;
1035 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
1036 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
1037 qInfo->tqi_burstTime = qi->tqi_burstTime;
1038 qInfo->tqi_readyTime = qi->tqi_readyTime;
1042 /* 11a Turbo 11b 11g 108g */
1043 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
1046 * Read the current channel noise floor and return.
1047 * If nf cal hasn't finished, channel noise floor should be 0
1048 * and we return a nominal value based on band and frequency.
1050 * NB: This is a private routine used by per-chip code to
1051 * implement the ah_getChanNoise method.
1054 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
1056 HAL_CHANNEL_INTERNAL *ichan;
1058 ichan = ath_hal_checkchannel(ah, chan);
1059 if (ichan == AH_NULL) {
1060 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1061 "%s: invalid channel %u/0x%x; no mapping\n",
1062 __func__, chan->ic_freq, chan->ic_flags);
1065 if (ichan->rawNoiseFloor == 0) {
1066 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1068 HALASSERT(mode < WIRELESS_MODE_MAX);
1069 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
1071 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
1075 * Fetch the current setup of ctl/ext noise floor values.
1077 * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
1078 * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
1080 * The caller must supply ctl/ext NF arrays which are at least
1081 * AH_MAX_CHAINS entries long.
1084 ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
1085 const struct ieee80211_channel *chan, int16_t *nf_ctl,
1088 #ifdef AH_SUPPORT_AR5416
1089 HAL_CHANNEL_INTERNAL *ichan;
1092 ichan = ath_hal_checkchannel(ah, chan);
1093 if (ichan == AH_NULL) {
1094 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1095 "%s: invalid channel %u/0x%x; no mapping\n",
1096 __func__, chan->ic_freq, chan->ic_flags);
1097 for (i = 0; i < AH_MAX_CHAINS; i++) {
1098 nf_ctl[i] = nf_ext[i] = 0;
1103 /* Return 0 if there's no valid MIMO values (yet) */
1104 if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
1105 for (i = 0; i < AH_MAX_CHAINS; i++) {
1106 nf_ctl[i] = nf_ext[i] = 0;
1110 if (ichan->rawNoiseFloor == 0) {
1111 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1112 HALASSERT(mode < WIRELESS_MODE_MAX);
1114 * See the comment below - this could cause issues for
1115 * stations which have a very low RSSI, below the
1116 * 'normalised' NF values in NOISE_FLOOR[].
1118 for (i = 0; i < AH_MAX_CHAINS; i++) {
1119 nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
1120 ath_hal_getNfAdjust(ah, ichan);
1125 * The value returned here from a MIMO radio is presumed to be
1126 * "good enough" as a NF calculation. As RSSI values are calculated
1127 * against this, an adjusted NF may be higher than the RSSI value
1128 * returned from a vary weak station, resulting in an obscenely
1129 * high signal strength calculation being returned.
1131 * This should be re-evaluated at a later date, along with any
1132 * signal strength calculations which are made. Quite likely the
1133 * RSSI values will need to be adjusted to ensure the calculations
1134 * don't "wrap" when RSSI is less than the "adjusted" NF value.
1135 * ("Adjust" here is via ichan->noiseFloorAdjust.)
1137 for (i = 0; i < AH_MAX_CHAINS; i++) {
1138 nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
1139 nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
1145 #endif /* AH_SUPPORT_AR5416 */
1149 * Process all valid raw noise floors into the dBm noise floor values.
1150 * Though our device has no reference for a dBm noise floor, we perform
1151 * a relative minimization of NF's based on the lowest NF found across a
1155 ath_hal_process_noisefloor(struct ath_hal *ah)
1157 HAL_CHANNEL_INTERNAL *c;
1158 int16_t correct2, correct5;
1159 int16_t lowest2, lowest5;
1163 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
1164 * for statistically recorded NF/channel deviation.
1166 correct2 = lowest2 = 0;
1167 correct5 = lowest5 = 0;
1168 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1172 c = &AH_PRIVATE(ah)->ah_channels[i];
1173 if (c->rawNoiseFloor >= 0)
1175 /* XXX can't identify proper mode */
1176 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
1177 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
1178 ath_hal_getNfAdjust(ah, c);
1179 if (IS_CHAN_5GHZ(c)) {
1182 correct5 = NOISE_FLOOR[mode] -
1183 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1188 correct2 = NOISE_FLOOR[mode] -
1189 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1194 /* Correct the channels to reach the expected NF value */
1195 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1196 c = &AH_PRIVATE(ah)->ah_channels[i];
1197 if (c->rawNoiseFloor >= 0)
1199 /* Apply correction factor */
1200 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
1201 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
1202 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
1203 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
1208 * INI support routines.
1212 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1217 HALASSERT(col < ia->cols);
1218 for (r = 0; r < ia->rows; r++) {
1219 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1220 HAL_INI_VAL(ia, r, col));
1222 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */
1223 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
1232 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1236 HALASSERT(col < ia->cols);
1237 for (r = 0; r < ia->rows; r++)
1238 data[r] = HAL_INI_VAL(ia, r, col);
1242 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1243 const uint32_t data[], int regWr)
1247 for (r = 0; r < ia->rows; r++) {
1248 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1255 * These are EEPROM board related routines which should likely live in
1256 * a helper library of some sort.
1259 /**************************************************************
1260 * ath_ee_getLowerUppderIndex
1262 * Return indices surrounding the value in sorted integer lists.
1263 * Requirement: the input list must be monotonically increasing
1264 * and populated up to the list size
1265 * Returns: match is set if an index in the array matches exactly
1266 * or a the target is before or after the range of the array.
1269 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1270 uint16_t *indexL, uint16_t *indexR)
1275 * Check first and last elements for beyond ordered array cases.
1277 if (target <= pList[0]) {
1278 *indexL = *indexR = 0;
1281 if (target >= pList[listSize-1]) {
1282 *indexL = *indexR = (uint16_t)(listSize - 1);
1286 /* look for value being near or between 2 values in list */
1287 for (i = 0; i < listSize - 1; i++) {
1289 * If value is close to the current value of the list
1290 * then target is not between values, it is one of the values
1292 if (pList[i] == target) {
1293 *indexL = *indexR = i;
1297 * Look for value being between current value and next value
1298 * if so return these 2 values
1300 if (target < pList[i + 1]) {
1302 *indexR = (uint16_t)(i + 1);
1307 *indexL = *indexR = 0;
1311 /**************************************************************
1312 * ath_ee_FillVpdTable
1314 * Fill the Vpdlist for indices Pmax-Pmin
1315 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1318 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1319 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1322 uint8_t currPwr = pwrMin;
1323 uint16_t idxL, idxR;
1325 HALASSERT(pwrMax > pwrMin);
1326 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1327 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1330 idxR = 1; /* extrapolate below */
1331 if (idxL == numIntercepts - 1)
1332 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */
1333 if (pPwrList[idxL] == pPwrList[idxR])
1336 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1337 (pPwrList[idxR] - pPwrList[idxL]) );
1339 pRetVpdList[i] = (uint8_t)k;
1340 currPwr += 2; /* half dB steps */
1346 /**************************************************************************
1347 * ath_ee_interpolate
1349 * Returns signed interpolated or the scaled up interpolated value
1352 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1353 int16_t targetLeft, int16_t targetRight)
1357 if (srcRight == srcLeft) {
1360 rv = (int16_t)( ((target - srcLeft) * targetRight +
1361 (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1370 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
1372 /* XXX handle wrap/overflow */
1373 OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
1377 * Enable or disable CCA.
1380 ath_hal_setcca(struct ath_hal *ah, int ena)
1383 * NB: fill me in; this is not provided by default because disabling
1384 * CCA in most locales violates regulatory.
1392 ath_hal_getcca(struct ath_hal *ah)
1395 if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
1397 return ((diag & 0x500000) == 0);
1401 * This routine is only needed when supporting EEPROM-in-RAM setups
1402 * (eg embedded SoCs and on-board PCI/PCIe devices.)
1404 /* NB: This is in 16 bit words; not bytes */
1405 /* XXX This doesn't belong here! */
1406 #define ATH_DATA_EEPROM_SIZE 2048
1409 ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data)
1411 if (ah->ah_eepromdata == AH_NULL) {
1412 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__);
1415 if (off > ATH_DATA_EEPROM_SIZE) {
1416 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n",
1417 __func__, off, ATH_DATA_EEPROM_SIZE);
1420 (*data) = ah->ah_eepromdata[off];
1425 * Do a 2GHz specific MHz->IEEE based on the hardware
1428 * This is the unmapped frequency which is programmed into the hardware.
1431 ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, int freq)
1437 return ((int) freq - 2407) / 5;
1439 return 15 + ((freq - 2512) / 20);
1443 * Clear the current survey data.
1445 * This should be done during a channel change.
1448 ath_hal_survey_clear(struct ath_hal *ah)
1451 OS_MEMZERO(&AH_PRIVATE(ah)->ah_chansurvey,
1452 sizeof(AH_PRIVATE(ah)->ah_chansurvey));
1456 * Add a sample to the channel survey.
1459 ath_hal_survey_add_sample(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs)
1461 HAL_CHANNEL_SURVEY *cs;
1463 cs = &AH_PRIVATE(ah)->ah_chansurvey;
1465 OS_MEMCPY(&cs->samples[cs->cur_sample], hs, sizeof(*hs));
1466 cs->samples[cs->cur_sample].seq_num = cs->cur_seq;
1467 cs->cur_sample = (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT;