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, HAL_STATUS *error)
60 struct ath_hal_chip * const *pchip;
62 OS_SET_FOREACH(pchip, ah_chips) {
63 struct ath_hal_chip *chip = *pchip;
66 /* XXX don't have vendorid, assume atheros one works */
67 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
69 ah = chip->attach(devid, sc, st, sh, eepromdata, error);
71 /* copy back private state to public area */
72 ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
73 ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
74 ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
75 ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
76 ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
77 ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
78 ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
86 ath_hal_mac_name(struct ath_hal *ah)
88 switch (ah->ah_macVersion) {
89 case AR_SREV_VERSION_CRETE:
90 case AR_SREV_VERSION_MAUI_1:
92 case AR_SREV_VERSION_MAUI_2:
93 case AR_SREV_VERSION_OAHU:
95 case AR_SREV_VERSION_VENICE:
97 case AR_SREV_VERSION_GRIFFIN:
99 case AR_SREV_VERSION_CONDOR:
101 case AR_SREV_VERSION_EAGLE:
103 case AR_SREV_VERSION_COBRA:
105 case AR_SREV_2425: /* Swan */
107 case AR_SREV_2417: /* Nala */
109 case AR_XSREV_VERSION_OWL_PCI:
111 case AR_XSREV_VERSION_OWL_PCIE:
113 case AR_XSREV_VERSION_HOWL:
115 case AR_XSREV_VERSION_SOWL:
117 case AR_XSREV_VERSION_MERLIN:
118 if (AH_PRIVATE(ah)->ah_ispcie)
121 case AR_XSREV_VERSION_KITE:
123 case AR_XSREV_VERSION_KIWI:
124 if (AH_PRIVATE(ah)->ah_ispcie)
127 case AR_SREV_VERSION_AR9380:
128 if (ah->ah_macRev >= AR_SREV_REVISION_AR9580_10)
131 case AR_SREV_VERSION_AR9460:
133 case AR_SREV_VERSION_AR9330:
135 case AR_SREV_VERSION_AR9340:
137 case AR_SREV_VERSION_QCA9550:
138 /* XXX should say QCA, not AR */
140 case AR_SREV_VERSION_AR9485:
142 case AR_SREV_VERSION_QCA9565:
143 /* XXX should say QCA, not AR */
150 * Return the mask of available modes based on the hardware capabilities.
153 ath_hal_getwirelessmodes(struct ath_hal*ah)
155 return ath_hal_getWirelessModes(ah);
158 /* linker set of registered RF backends */
159 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
162 * Check the set of registered RF backends to see if
163 * any recognize the device as one they can support.
166 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
168 struct ath_hal_rf * const *prf;
170 OS_SET_FOREACH(prf, ah_rfs) {
171 struct ath_hal_rf *rf = *prf;
175 *ecode = HAL_ENOTSUPP;
180 ath_hal_rf_name(struct ath_hal *ah)
182 switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
184 return "5110"; /* NB: made up */
185 case AR_RAD5111_SREV_MAJOR:
186 case AR_RAD5111_SREV_PROD:
188 case AR_RAD2111_SREV_MAJOR:
190 case AR_RAD5112_SREV_MAJOR:
191 case AR_RAD5112_SREV_2_0:
192 case AR_RAD5112_SREV_2_1:
194 case AR_RAD2112_SREV_MAJOR:
195 case AR_RAD2112_SREV_2_0:
196 case AR_RAD2112_SREV_2_1:
198 case AR_RAD2413_SREV_MAJOR:
200 case AR_RAD5413_SREV_MAJOR:
202 case AR_RAD2316_SREV_MAJOR:
204 case AR_RAD2317_SREV_MAJOR:
206 case AR_RAD5424_SREV_MAJOR:
209 case AR_RAD5133_SREV_MAJOR:
211 case AR_RAD2133_SREV_MAJOR:
213 case AR_RAD5122_SREV_MAJOR:
215 case AR_RAD2122_SREV_MAJOR:
222 * Poll the register looking for a specific value.
225 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
227 #define AH_TIMEOUT 1000
228 return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
233 ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
237 for (i = 0; i < timeout; i++) {
238 if ((OS_REG_READ(ah, reg) & mask) == val)
242 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
243 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
244 __func__, reg, OS_REG_READ(ah, reg), mask, val);
249 * Reverse the bits starting at the low bit for a value of
253 ath_hal_reverseBits(uint32_t val, uint32_t n)
258 for (i = 0, retval = 0; i < n; i++) {
259 retval = (retval << 1) | (val & 1);
265 /* 802.11n related timing definitions */
267 #define OFDM_PLCP_BITS 22
273 #define HT_LTF(n) ((n) * 4)
275 #define HT_RC_2_MCS(_rc) ((_rc) & 0xf)
276 #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
277 #define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS)
280 * Calculate the duration of a packet whether it is 11n or legacy.
283 ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
284 uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
289 rc = rates->info[rateix].rateCode;
291 /* Legacy rate? Return the old way */
292 if (! IS_HT_RATE(rc))
293 return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
295 /* 11n frame - extract out the number of spatial streams */
296 numStreams = HT_RC_2_STREAMS(rc);
297 KASSERT(numStreams > 0 && numStreams <= 4,
298 ("number of spatial streams needs to be 1..3: MCS rate 0x%x!",
301 return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
304 static const uint16_t ht20_bps[32] = {
305 26, 52, 78, 104, 156, 208, 234, 260,
306 52, 104, 156, 208, 312, 416, 468, 520,
307 78, 156, 234, 312, 468, 624, 702, 780,
308 104, 208, 312, 416, 624, 832, 936, 1040
310 static const uint16_t ht40_bps[32] = {
311 54, 108, 162, 216, 324, 432, 486, 540,
312 108, 216, 324, 432, 648, 864, 972, 1080,
313 162, 324, 486, 648, 972, 1296, 1458, 1620,
314 216, 432, 648, 864, 1296, 1728, 1944, 2160
318 * Calculate the transmit duration of an 11n frame.
321 ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams,
322 HAL_BOOL isht40, HAL_BOOL isShortGI)
324 uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
326 KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
327 KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate));
330 bitsPerSymbol = ht40_bps[rate & 0x1f];
332 bitsPerSymbol = ht20_bps[rate & 0x1f];
333 numBits = OFDM_PLCP_BITS + (frameLen << 3);
334 numSymbols = howmany(numBits, bitsPerSymbol);
336 txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */
338 txTime = numSymbols * 4; /* 4us */
339 return txTime + HT_L_STF + HT_L_LTF +
340 HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
344 * Compute the time to transmit a frame of length frameLen bytes
345 * using the specified rate, phy, and short preamble setting.
348 ath_hal_computetxtime(struct ath_hal *ah,
349 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
350 HAL_BOOL shortPreamble)
352 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
355 /* Warn if this function is called for 11n rates; it should not be! */
356 if (IS_HT_RATE(rates->info[rateix].rateCode))
357 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
358 __func__, rateix, rates->info[rateix].rateCode);
360 kbps = rates->info[rateix].rateKbps;
362 * index can be invalid duting dynamic Turbo transitions.
367 switch (rates->info[rateix].phy) {
368 case IEEE80211_T_CCK:
369 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
370 if (shortPreamble && rates->info[rateix].shortPreamble)
372 numBits = frameLen << 3;
373 txTime = CCK_SIFS_TIME + phyTime
374 + ((numBits * 1000)/kbps);
376 case IEEE80211_T_OFDM:
377 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
378 HALASSERT(bitsPerSymbol != 0);
380 numBits = OFDM_PLCP_BITS + (frameLen << 3);
381 numSymbols = howmany(numBits, bitsPerSymbol);
382 txTime = OFDM_SIFS_TIME
384 + (numSymbols * OFDM_SYMBOL_TIME);
386 case IEEE80211_T_OFDM_HALF:
387 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
388 HALASSERT(bitsPerSymbol != 0);
390 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3);
391 numSymbols = howmany(numBits, bitsPerSymbol);
392 txTime = OFDM_HALF_SIFS_TIME
393 + OFDM_HALF_PREAMBLE_TIME
394 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
396 case IEEE80211_T_OFDM_QUARTER:
397 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
398 HALASSERT(bitsPerSymbol != 0);
400 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
401 numSymbols = howmany(numBits, bitsPerSymbol);
402 txTime = OFDM_QUARTER_SIFS_TIME
403 + OFDM_QUARTER_PREAMBLE_TIME
404 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
406 case IEEE80211_T_TURBO:
407 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000;
408 HALASSERT(bitsPerSymbol != 0);
410 numBits = TURBO_PLCP_BITS + (frameLen << 3);
411 numSymbols = howmany(numBits, bitsPerSymbol);
412 txTime = TURBO_SIFS_TIME
413 + TURBO_PREAMBLE_TIME
414 + (numSymbols * TURBO_SYMBOL_TIME);
417 HALDEBUG(ah, HAL_DEBUG_PHYIO,
418 "%s: unknown phy %u (rate ix %u)\n",
419 __func__, rates->info[rateix].phy, rateix);
427 ath_hal_get_curmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
430 * Pick a default mode at bootup. A channel change is inevitable.
433 return HAL_MODE_11NG_HT20;
435 if (IEEE80211_IS_CHAN_TURBO(chan))
436 return HAL_MODE_TURBO;
438 /* check for NA_HT before plain A, since IS_CHAN_A includes NA_HT */
439 if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
440 return HAL_MODE_11NA_HT20;
441 if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
442 return HAL_MODE_11NA_HT40PLUS;
443 if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
444 return HAL_MODE_11NA_HT40MINUS;
445 if (IEEE80211_IS_CHAN_A(chan))
448 /* check for NG_HT before plain G, since IS_CHAN_G includes NG_HT */
449 if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
450 return HAL_MODE_11NG_HT20;
451 if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
452 return HAL_MODE_11NG_HT40PLUS;
453 if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
454 return HAL_MODE_11NG_HT40MINUS;
457 * XXX For FreeBSD, will this work correctly given the DYN
458 * chan mode (OFDM+CCK dynamic) ? We have pure-G versions DYN-BG..
460 if (IEEE80211_IS_CHAN_G(chan))
462 if (IEEE80211_IS_CHAN_B(chan))
466 return HAL_MODE_11NG_HT20;
471 WIRELESS_MODE_11a = 0,
472 WIRELESS_MODE_TURBO = 1,
473 WIRELESS_MODE_11b = 2,
474 WIRELESS_MODE_11g = 3,
475 WIRELESS_MODE_108g = 4,
481 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
483 if (IEEE80211_IS_CHAN_B(chan))
484 return WIRELESS_MODE_11b;
485 if (IEEE80211_IS_CHAN_G(chan))
486 return WIRELESS_MODE_11g;
487 if (IEEE80211_IS_CHAN_108G(chan))
488 return WIRELESS_MODE_108g;
489 if (IEEE80211_IS_CHAN_TURBO(chan))
490 return WIRELESS_MODE_TURBO;
491 return WIRELESS_MODE_11a;
495 * Convert between microseconds and core system clocks.
497 /* 11a Turbo 11b 11g 108g */
498 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
500 #define CLOCK_FAST_RATE_5GHZ_OFDM 44
503 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
505 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
508 /* NB: ah_curchan may be null when called attach time */
509 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
510 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
511 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
512 if (IEEE80211_IS_CHAN_HT40(c))
514 } else if (c != AH_NULL) {
515 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
516 if (IEEE80211_IS_CHAN_HT40(c))
519 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
521 /* Compensate for half/quarter rate */
522 if (c != AH_NULL && IEEE80211_IS_CHAN_HALF(c))
524 else if (c != AH_NULL && IEEE80211_IS_CHAN_QUARTER(c))
531 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
533 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
536 /* NB: ah_curchan may be null when called attach time */
537 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
538 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
539 usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
540 if (IEEE80211_IS_CHAN_HT40(c))
542 } else if (c != AH_NULL) {
543 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
544 if (IEEE80211_IS_CHAN_HT40(c))
547 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
552 * Setup a h/w rate table's reverse lookup table and
553 * fill in ack durations. This routine is called for
554 * each rate table returned through the ah_getRateTable
555 * method. The reverse lookup tables are assumed to be
556 * initialized to zero (or at least the first entry).
557 * We use this as a key that indicates whether or not
558 * we've previously setup the reverse lookup table.
560 * XXX not reentrant, but shouldn't matter
563 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
565 #define N(a) (sizeof(a)/sizeof(a[0]))
568 if (rt->rateCodeToIndex[0] != 0) /* already setup */
570 for (i = 0; i < N(rt->rateCodeToIndex); i++)
571 rt->rateCodeToIndex[i] = (uint8_t) -1;
572 for (i = 0; i < rt->rateCount; i++) {
573 uint8_t code = rt->info[i].rateCode;
574 uint8_t cix = rt->info[i].controlRate;
576 HALASSERT(code < N(rt->rateCodeToIndex));
577 rt->rateCodeToIndex[code] = i;
578 HALASSERT((code | rt->info[i].shortPreamble) <
579 N(rt->rateCodeToIndex));
580 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
582 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
583 * depends on whether they are marked as basic rates;
584 * the static tables are setup with an 11b-compatible
585 * 2Mb/s rate which will work but is suboptimal
587 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
588 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
589 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
590 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
596 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
597 uint32_t capability, uint32_t *result)
599 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
602 case HAL_CAP_REG_DMN: /* regulatory domain */
603 *result = AH_PRIVATE(ah)->ah_currentRD;
605 case HAL_CAP_DFS_DMN: /* DFS Domain */
606 *result = AH_PRIVATE(ah)->ah_dfsDomain;
608 case HAL_CAP_CIPHER: /* cipher handled in hardware */
609 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
611 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
613 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
614 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
615 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
617 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
619 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
620 *result = pCap->halKeyCacheSize;
622 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
623 *result = pCap->halTotalQueues;
625 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
626 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
627 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
628 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
629 case HAL_CAP_COMPRESSION:
630 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
632 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
633 case HAL_CAP_FASTFRAME:
634 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
635 case HAL_CAP_DIAG: /* hardware diagnostic support */
636 *result = AH_PRIVATE(ah)->ah_diagreg;
638 case HAL_CAP_TXPOW: /* global tx power limit */
639 switch (capability) {
640 case 0: /* facility is supported */
642 case 1: /* current limit */
643 *result = AH_PRIVATE(ah)->ah_powerLimit;
645 case 2: /* current max tx power */
646 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
648 case 3: /* scale factor */
649 *result = AH_PRIVATE(ah)->ah_tpScale;
653 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
654 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
655 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
656 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
657 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
659 case HAL_CAP_RFSILENT: /* rfsilent support */
660 switch (capability) {
661 case 0: /* facility is supported */
662 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
663 case 1: /* current setting */
664 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
665 HAL_OK : HAL_ENOTSUPP;
666 case 2: /* rfsilent config */
667 *result = AH_PRIVATE(ah)->ah_rfsilent;
675 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
677 return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
678 case HAL_CAP_FAST_CC:
679 return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
680 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
681 *result = pCap->halTxChainMask;
683 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
684 *result = pCap->halRxChainMask;
686 case HAL_CAP_NUM_GPIO_PINS:
687 *result = pCap->halNumGpioPins;
690 return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
691 case HAL_CAP_RTS_AGGR_LIMIT:
692 *result = pCap->halRtsAggrLimit;
694 case HAL_CAP_4ADDR_AGGR:
695 return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
696 case HAL_CAP_EXT_CHAN_DFS:
697 return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
698 case HAL_CAP_RX_STBC:
699 return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
700 case HAL_CAP_TX_STBC:
701 return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
702 case HAL_CAP_COMBINED_RADAR_RSSI:
703 return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
704 case HAL_CAP_AUTO_SLEEP:
705 return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
706 case HAL_CAP_MBSSID_AGGR_SUPPORT:
707 return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
708 case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */
709 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
710 case HAL_CAP_REG_FLAG:
711 *result = AH_PRIVATE(ah)->ah_currentRDext;
713 case HAL_CAP_ENHANCED_DMA_SUPPORT:
714 return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP;
715 case HAL_CAP_NUM_TXMAPS:
716 *result = pCap->halNumTxMaps;
718 case HAL_CAP_TXDESCLEN:
719 *result = pCap->halTxDescLen;
721 case HAL_CAP_TXSTATUSLEN:
722 *result = pCap->halTxStatusLen;
724 case HAL_CAP_RXSTATUSLEN:
725 *result = pCap->halRxStatusLen;
727 case HAL_CAP_RXFIFODEPTH:
728 switch (capability) {
729 case HAL_RX_QUEUE_HP:
730 *result = pCap->halRxHpFifoDepth;
732 case HAL_RX_QUEUE_LP:
733 *result = pCap->halRxLpFifoDepth;
738 case HAL_CAP_RXBUFSIZE:
739 case HAL_CAP_NUM_MR_RETRIES:
740 *result = pCap->halNumMRRetries;
742 case HAL_CAP_BT_COEX:
743 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
744 case HAL_CAP_SPECTRAL_SCAN:
745 return pCap->halSpectralScanSupport ? HAL_OK : HAL_ENOTSUPP;
746 case HAL_CAP_HT20_SGI:
747 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
748 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
749 *result = pCap->halTstampPrecision;
751 case HAL_CAP_ANT_DIV_COMB: /* AR9285/AR9485 LNA diversity */
752 return pCap->halAntDivCombSupport ? HAL_OK : HAL_ENOTSUPP;
754 case HAL_CAP_ENHANCED_DFS_SUPPORT:
755 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
757 /* FreeBSD-specific entries for now */
758 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
759 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
760 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
761 *result = pCap->halIntrMask;
763 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
764 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
765 case HAL_CAP_STREAMS: /* number of 11n spatial streams */
766 switch (capability) {
768 *result = pCap->halTxStreams;
771 *result = pCap->halRxStreams;
776 case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */
777 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
778 case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */
779 return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP;
780 case HAL_CAP_BB_READ_WAR: /* Baseband read WAR */
781 return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP;
782 case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */
783 return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP;
784 case HAL_CAP_MFP: /* Management frame protection setting */
785 *result = pCap->halMfpSupport;
787 case HAL_CAP_RX_LNA_MIXING: /* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */
788 return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP;
795 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
796 uint32_t capability, uint32_t setting, HAL_STATUS *status)
801 switch (capability) {
803 if (setting <= HAL_TP_SCALE_MIN) {
804 AH_PRIVATE(ah)->ah_tpScale = setting;
810 case HAL_CAP_RFSILENT: /* rfsilent support */
812 * NB: allow even if halRfSilentSupport is false
813 * in case the EEPROM is misprogrammed.
815 switch (capability) {
816 case 1: /* current setting */
817 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
819 case 2: /* rfsilent config */
820 /* XXX better done per-chip for validation? */
821 AH_PRIVATE(ah)->ah_rfsilent = setting;
825 case HAL_CAP_REG_DMN: /* regulatory domain */
826 AH_PRIVATE(ah)->ah_currentRD = setting;
828 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
829 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
835 *status = HAL_EINVAL;
840 * Common support for getDiagState method.
844 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
845 void *dstbuf, int space)
847 uint32_t *dp = dstbuf;
850 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
851 u_int r = regs[i].start;
852 u_int e = regs[i].end;
854 space -= sizeof(uint32_t);
856 *dp++ = OS_REG_READ(ah, r);
857 r += sizeof(uint32_t);
858 space -= sizeof(uint32_t);
859 } while (r <= e && space >= sizeof(uint32_t));
861 return (char *) dp - (char *) dstbuf;
865 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
867 while (space >= sizeof(HAL_REGWRITE)) {
868 OS_REG_WRITE(ah, regs->addr, regs->value);
869 regs++, space -= sizeof(HAL_REGWRITE);
874 ath_hal_getdiagstate(struct ath_hal *ah, int request,
875 const void *args, uint32_t argsize,
876 void **result, uint32_t *resultsize)
880 *result = &AH_PRIVATE(ah)->ah_devid;
881 *resultsize = sizeof(HAL_REVS);
884 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
886 case HAL_DIAG_SETREGS:
887 ath_hal_setregs(ah, args, argsize);
890 case HAL_DIAG_FATALERR:
891 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
892 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
894 case HAL_DIAG_EEREAD:
895 if (argsize != sizeof(uint16_t))
897 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
899 *resultsize = sizeof(uint16_t);
901 #ifdef AH_PRIVATE_DIAG
902 case HAL_DIAG_SETKEY: {
903 const HAL_DIAG_KEYVAL *dk;
905 if (argsize != sizeof(HAL_DIAG_KEYVAL))
907 dk = (const HAL_DIAG_KEYVAL *)args;
908 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
909 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
911 case HAL_DIAG_RESETKEY:
912 if (argsize != sizeof(uint16_t))
914 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
915 #ifdef AH_SUPPORT_WRITE_EEPROM
916 case HAL_DIAG_EEWRITE: {
917 const HAL_DIAG_EEVAL *ee;
918 if (argsize != sizeof(HAL_DIAG_EEVAL))
920 ee = (const HAL_DIAG_EEVAL *)args;
921 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
923 #endif /* AH_SUPPORT_WRITE_EEPROM */
924 #endif /* AH_PRIVATE_DIAG */
925 case HAL_DIAG_11NCOMPAT:
927 *resultsize = sizeof(uint32_t);
928 *((uint32_t *)(*result)) =
929 AH_PRIVATE(ah)->ah_11nCompat;
930 } else if (argsize == sizeof(uint32_t)) {
931 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
940 * Set the properties of the tx queue with the parameters
944 ath_hal_setTxQProps(struct ath_hal *ah,
945 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
949 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
950 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
951 "%s: inactive queue\n", __func__);
954 /* XXX validate parameters */
955 qi->tqi_ver = qInfo->tqi_ver;
956 qi->tqi_subtype = qInfo->tqi_subtype;
957 qi->tqi_qflags = qInfo->tqi_qflags;
958 qi->tqi_priority = qInfo->tqi_priority;
959 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
960 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
962 qi->tqi_aifs = INIT_AIFS;
963 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
964 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
965 /* make sure that the CWmin is of the form (2^n - 1) */
967 while (qi->tqi_cwmin < cw)
968 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
970 qi->tqi_cwmin = qInfo->tqi_cwmin;
971 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
972 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
973 /* make sure that the CWmax is of the form (2^n - 1) */
975 while (qi->tqi_cwmax < cw)
976 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
978 qi->tqi_cwmax = INIT_CWMAX;
979 /* Set retry limit values */
980 if (qInfo->tqi_shretry != 0)
981 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
983 qi->tqi_shretry = INIT_SH_RETRY;
984 if (qInfo->tqi_lgretry != 0)
985 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
987 qi->tqi_lgretry = INIT_LG_RETRY;
988 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
989 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
990 qi->tqi_burstTime = qInfo->tqi_burstTime;
991 qi->tqi_readyTime = qInfo->tqi_readyTime;
993 switch (qInfo->tqi_subtype) {
995 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
996 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
999 break; /* NB: silence compiler */
1005 ath_hal_getTxQProps(struct ath_hal *ah,
1006 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
1008 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
1009 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
1010 "%s: inactive queue\n", __func__);
1014 qInfo->tqi_qflags = qi->tqi_qflags;
1015 qInfo->tqi_ver = qi->tqi_ver;
1016 qInfo->tqi_subtype = qi->tqi_subtype;
1017 qInfo->tqi_qflags = qi->tqi_qflags;
1018 qInfo->tqi_priority = qi->tqi_priority;
1019 qInfo->tqi_aifs = qi->tqi_aifs;
1020 qInfo->tqi_cwmin = qi->tqi_cwmin;
1021 qInfo->tqi_cwmax = qi->tqi_cwmax;
1022 qInfo->tqi_shretry = qi->tqi_shretry;
1023 qInfo->tqi_lgretry = qi->tqi_lgretry;
1024 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
1025 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
1026 qInfo->tqi_burstTime = qi->tqi_burstTime;
1027 qInfo->tqi_readyTime = qi->tqi_readyTime;
1031 /* 11a Turbo 11b 11g 108g */
1032 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
1035 * Read the current channel noise floor and return.
1036 * If nf cal hasn't finished, channel noise floor should be 0
1037 * and we return a nominal value based on band and frequency.
1039 * NB: This is a private routine used by per-chip code to
1040 * implement the ah_getChanNoise method.
1043 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
1045 HAL_CHANNEL_INTERNAL *ichan;
1047 ichan = ath_hal_checkchannel(ah, chan);
1048 if (ichan == AH_NULL) {
1049 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1050 "%s: invalid channel %u/0x%x; no mapping\n",
1051 __func__, chan->ic_freq, chan->ic_flags);
1054 if (ichan->rawNoiseFloor == 0) {
1055 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1057 HALASSERT(mode < WIRELESS_MODE_MAX);
1058 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
1060 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
1064 * Fetch the current setup of ctl/ext noise floor values.
1066 * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
1067 * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
1069 * The caller must supply ctl/ext NF arrays which are at least
1070 * AH_MAX_CHAINS entries long.
1073 ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
1074 const struct ieee80211_channel *chan, int16_t *nf_ctl,
1077 #ifdef AH_SUPPORT_AR5416
1078 HAL_CHANNEL_INTERNAL *ichan;
1081 ichan = ath_hal_checkchannel(ah, chan);
1082 if (ichan == AH_NULL) {
1083 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1084 "%s: invalid channel %u/0x%x; no mapping\n",
1085 __func__, chan->ic_freq, chan->ic_flags);
1086 for (i = 0; i < AH_MAX_CHAINS; i++) {
1087 nf_ctl[i] = nf_ext[i] = 0;
1092 /* Return 0 if there's no valid MIMO values (yet) */
1093 if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
1094 for (i = 0; i < AH_MAX_CHAINS; i++) {
1095 nf_ctl[i] = nf_ext[i] = 0;
1099 if (ichan->rawNoiseFloor == 0) {
1100 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1101 HALASSERT(mode < WIRELESS_MODE_MAX);
1103 * See the comment below - this could cause issues for
1104 * stations which have a very low RSSI, below the
1105 * 'normalised' NF values in NOISE_FLOOR[].
1107 for (i = 0; i < AH_MAX_CHAINS; i++) {
1108 nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
1109 ath_hal_getNfAdjust(ah, ichan);
1114 * The value returned here from a MIMO radio is presumed to be
1115 * "good enough" as a NF calculation. As RSSI values are calculated
1116 * against this, an adjusted NF may be higher than the RSSI value
1117 * returned from a vary weak station, resulting in an obscenely
1118 * high signal strength calculation being returned.
1120 * This should be re-evaluated at a later date, along with any
1121 * signal strength calculations which are made. Quite likely the
1122 * RSSI values will need to be adjusted to ensure the calculations
1123 * don't "wrap" when RSSI is less than the "adjusted" NF value.
1124 * ("Adjust" here is via ichan->noiseFloorAdjust.)
1126 for (i = 0; i < AH_MAX_CHAINS; i++) {
1127 nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
1128 nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
1134 #endif /* AH_SUPPORT_AR5416 */
1138 * Process all valid raw noise floors into the dBm noise floor values.
1139 * Though our device has no reference for a dBm noise floor, we perform
1140 * a relative minimization of NF's based on the lowest NF found across a
1144 ath_hal_process_noisefloor(struct ath_hal *ah)
1146 HAL_CHANNEL_INTERNAL *c;
1147 int16_t correct2, correct5;
1148 int16_t lowest2, lowest5;
1152 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
1153 * for statistically recorded NF/channel deviation.
1155 correct2 = lowest2 = 0;
1156 correct5 = lowest5 = 0;
1157 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1161 c = &AH_PRIVATE(ah)->ah_channels[i];
1162 if (c->rawNoiseFloor >= 0)
1164 /* XXX can't identify proper mode */
1165 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
1166 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
1167 ath_hal_getNfAdjust(ah, c);
1168 if (IS_CHAN_5GHZ(c)) {
1171 correct5 = NOISE_FLOOR[mode] -
1172 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1177 correct2 = NOISE_FLOOR[mode] -
1178 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1183 /* Correct the channels to reach the expected NF value */
1184 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1185 c = &AH_PRIVATE(ah)->ah_channels[i];
1186 if (c->rawNoiseFloor >= 0)
1188 /* Apply correction factor */
1189 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
1190 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
1191 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
1192 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
1197 * INI support routines.
1201 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1206 HALASSERT(col < ia->cols);
1207 for (r = 0; r < ia->rows; r++) {
1208 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1209 HAL_INI_VAL(ia, r, col));
1211 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */
1212 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
1221 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1225 HALASSERT(col < ia->cols);
1226 for (r = 0; r < ia->rows; r++)
1227 data[r] = HAL_INI_VAL(ia, r, col);
1231 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1232 const uint32_t data[], int regWr)
1236 for (r = 0; r < ia->rows; r++) {
1237 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1244 * These are EEPROM board related routines which should likely live in
1245 * a helper library of some sort.
1248 /**************************************************************
1249 * ath_ee_getLowerUppderIndex
1251 * Return indices surrounding the value in sorted integer lists.
1252 * Requirement: the input list must be monotonically increasing
1253 * and populated up to the list size
1254 * Returns: match is set if an index in the array matches exactly
1255 * or a the target is before or after the range of the array.
1258 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1259 uint16_t *indexL, uint16_t *indexR)
1264 * Check first and last elements for beyond ordered array cases.
1266 if (target <= pList[0]) {
1267 *indexL = *indexR = 0;
1270 if (target >= pList[listSize-1]) {
1271 *indexL = *indexR = (uint16_t)(listSize - 1);
1275 /* look for value being near or between 2 values in list */
1276 for (i = 0; i < listSize - 1; i++) {
1278 * If value is close to the current value of the list
1279 * then target is not between values, it is one of the values
1281 if (pList[i] == target) {
1282 *indexL = *indexR = i;
1286 * Look for value being between current value and next value
1287 * if so return these 2 values
1289 if (target < pList[i + 1]) {
1291 *indexR = (uint16_t)(i + 1);
1296 *indexL = *indexR = 0;
1300 /**************************************************************
1301 * ath_ee_FillVpdTable
1303 * Fill the Vpdlist for indices Pmax-Pmin
1304 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1307 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1308 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1311 uint8_t currPwr = pwrMin;
1312 uint16_t idxL, idxR;
1314 HALASSERT(pwrMax > pwrMin);
1315 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1316 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1319 idxR = 1; /* extrapolate below */
1320 if (idxL == numIntercepts - 1)
1321 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */
1322 if (pPwrList[idxL] == pPwrList[idxR])
1325 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1326 (pPwrList[idxR] - pPwrList[idxL]) );
1328 pRetVpdList[i] = (uint8_t)k;
1329 currPwr += 2; /* half dB steps */
1335 /**************************************************************************
1336 * ath_ee_interpolate
1338 * Returns signed interpolated or the scaled up interpolated value
1341 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1342 int16_t targetLeft, int16_t targetRight)
1346 if (srcRight == srcLeft) {
1349 rv = (int16_t)( ((target - srcLeft) * targetRight +
1350 (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1359 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
1361 /* XXX handle wrap/overflow */
1362 OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
1366 * Enable or disable CCA.
1369 ath_hal_setcca(struct ath_hal *ah, int ena)
1372 * NB: fill me in; this is not provided by default because disabling
1373 * CCA in most locales violates regulatory.
1381 ath_hal_getcca(struct ath_hal *ah)
1384 if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
1386 return ((diag & 0x500000) == 0);
1390 * This routine is only needed when supporting EEPROM-in-RAM setups
1391 * (eg embedded SoCs and on-board PCI/PCIe devices.)
1393 /* NB: This is in 16 bit words; not bytes */
1394 /* XXX This doesn't belong here! */
1395 #define ATH_DATA_EEPROM_SIZE 2048
1398 ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data)
1400 if (ah->ah_eepromdata == AH_NULL) {
1401 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__);
1404 if (off > ATH_DATA_EEPROM_SIZE) {
1405 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n",
1406 __func__, off, ATH_DATA_EEPROM_SIZE);
1409 (*data) = ah->ah_eepromdata[off];
1414 * Do a 2GHz specific MHz->IEEE based on the hardware
1417 * This is the unmapped frequency which is programmed into the hardware.
1420 ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
1423 if (ichan->channel == 2484)
1425 if (ichan->channel < 2484)
1426 return ((int) ichan->channel - 2407) / 5;
1428 return 15 + ((ichan->channel - 2512) / 20);