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 */
28 /* linker set of registered chips */
29 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
32 * Check the set of registered chips to see if any recognize
33 * the device as one they can support.
36 ath_hal_probe(uint16_t vendorid, uint16_t devid)
38 struct ath_hal_chip * const *pchip;
40 OS_SET_FOREACH(pchip, ah_chips) {
41 const char *name = (*pchip)->probe(vendorid, devid);
49 * Attach detects device chip revisions, initializes the hwLayer
50 * function list, reads EEPROM information,
51 * selects reset vectors, and performs a short self test.
52 * Any failures will return an error that should cause a hardware
56 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
57 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *error)
59 struct ath_hal_chip * const *pchip;
61 OS_SET_FOREACH(pchip, ah_chips) {
62 struct ath_hal_chip *chip = *pchip;
65 /* XXX don't have vendorid, assume atheros one works */
66 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
68 ah = chip->attach(devid, sc, st, sh, eepromdata, error);
70 /* copy back private state to public area */
71 ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
72 ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
73 ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
74 ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
75 ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
76 ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
77 ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
85 ath_hal_mac_name(struct ath_hal *ah)
87 switch (ah->ah_macVersion) {
88 case AR_SREV_VERSION_CRETE:
89 case AR_SREV_VERSION_MAUI_1:
91 case AR_SREV_VERSION_MAUI_2:
92 case AR_SREV_VERSION_OAHU:
94 case AR_SREV_VERSION_VENICE:
96 case AR_SREV_VERSION_GRIFFIN:
98 case AR_SREV_VERSION_CONDOR:
100 case AR_SREV_VERSION_EAGLE:
102 case AR_SREV_VERSION_COBRA:
108 case AR_XSREV_VERSION_OWL_PCI:
110 case AR_XSREV_VERSION_OWL_PCIE:
112 case AR_XSREV_VERSION_HOWL:
114 case AR_XSREV_VERSION_SOWL:
116 case AR_XSREV_VERSION_MERLIN:
117 if (AH_PRIVATE(ah)->ah_ispcie)
120 case AR_XSREV_VERSION_KITE:
122 case AR_XSREV_VERSION_KIWI:
123 if (AH_PRIVATE(ah)->ah_ispcie)
131 * Return the mask of available modes based on the hardware capabilities.
134 ath_hal_getwirelessmodes(struct ath_hal*ah)
136 return ath_hal_getWirelessModes(ah);
139 /* linker set of registered RF backends */
140 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
143 * Check the set of registered RF backends to see if
144 * any recognize the device as one they can support.
147 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
149 struct ath_hal_rf * const *prf;
151 OS_SET_FOREACH(prf, ah_rfs) {
152 struct ath_hal_rf *rf = *prf;
156 *ecode = HAL_ENOTSUPP;
161 ath_hal_rf_name(struct ath_hal *ah)
163 switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
165 return "5110"; /* NB: made up */
166 case AR_RAD5111_SREV_MAJOR:
167 case AR_RAD5111_SREV_PROD:
169 case AR_RAD2111_SREV_MAJOR:
171 case AR_RAD5112_SREV_MAJOR:
172 case AR_RAD5112_SREV_2_0:
173 case AR_RAD5112_SREV_2_1:
175 case AR_RAD2112_SREV_MAJOR:
176 case AR_RAD2112_SREV_2_0:
177 case AR_RAD2112_SREV_2_1:
179 case AR_RAD2413_SREV_MAJOR:
181 case AR_RAD5413_SREV_MAJOR:
183 case AR_RAD2316_SREV_MAJOR:
185 case AR_RAD2317_SREV_MAJOR:
187 case AR_RAD5424_SREV_MAJOR:
190 case AR_RAD5133_SREV_MAJOR:
192 case AR_RAD2133_SREV_MAJOR:
194 case AR_RAD5122_SREV_MAJOR:
196 case AR_RAD2122_SREV_MAJOR:
203 * Poll the register looking for a specific value.
206 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
208 #define AH_TIMEOUT 1000
209 return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
214 ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
218 for (i = 0; i < timeout; i++) {
219 if ((OS_REG_READ(ah, reg) & mask) == val)
223 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
224 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
225 __func__, reg, OS_REG_READ(ah, reg), mask, val);
230 * Reverse the bits starting at the low bit for a value of
234 ath_hal_reverseBits(uint32_t val, uint32_t n)
239 for (i = 0, retval = 0; i < n; i++) {
240 retval = (retval << 1) | (val & 1);
246 /* 802.11n related timing definitions */
248 #define OFDM_PLCP_BITS 22
254 #define HT_LTF(n) ((n) * 4)
256 #define HT_RC_2_MCS(_rc) ((_rc) & 0xf)
257 #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
258 #define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS)
261 * Calculate the duration of a packet whether it is 11n or legacy.
264 ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
265 uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble)
270 rc = rates->info[rateix].rateCode;
272 /* Legacy rate? Return the old way */
273 if (! IS_HT_RATE(rc))
274 return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble);
276 /* 11n frame - extract out the number of spatial streams */
277 numStreams = HT_RC_2_STREAMS(rc);
278 KASSERT(numStreams == 1 || numStreams == 2, ("number of spatial streams needs to be 1 or 2: MCS rate 0x%x!", rateix));
280 return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble);
284 * Calculate the transmit duration of an 11n frame.
285 * This only works for MCS0->MCS15.
288 ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, HAL_BOOL isht40,
291 static const uint16_t ht20_bps[16] = {
292 26, 52, 78, 104, 156, 208, 234, 260,
293 52, 104, 156, 208, 312, 416, 468, 520
295 static const uint16_t ht40_bps[16] = {
296 54, 108, 162, 216, 324, 432, 486, 540,
297 108, 216, 324, 432, 648, 864, 972, 1080,
299 uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
301 KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
302 KASSERT((rate &~ IEEE80211_RATE_MCS) < 16, ("bad mcs 0x%x", rate));
305 bitsPerSymbol = ht40_bps[rate & 0xf];
307 bitsPerSymbol = ht20_bps[rate & 0xf];
308 numBits = OFDM_PLCP_BITS + (frameLen << 3);
309 numSymbols = howmany(numBits, bitsPerSymbol);
311 txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */
313 txTime = numSymbols * 4; /* 4us */
314 return txTime + HT_L_STF + HT_L_LTF +
315 HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
319 * Compute the time to transmit a frame of length frameLen bytes
320 * using the specified rate, phy, and short preamble setting.
323 ath_hal_computetxtime(struct ath_hal *ah,
324 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
325 HAL_BOOL shortPreamble)
327 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
330 /* Warn if this function is called for 11n rates; it should not be! */
331 if (IS_HT_RATE(rates->info[rateix].rateCode))
332 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
333 __func__, rateix, rates->info[rateix].rateCode);
335 kbps = rates->info[rateix].rateKbps;
337 * index can be invalid duting dynamic Turbo transitions.
342 switch (rates->info[rateix].phy) {
343 case IEEE80211_T_CCK:
344 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
345 if (shortPreamble && rates->info[rateix].shortPreamble)
347 numBits = frameLen << 3;
348 txTime = CCK_SIFS_TIME + phyTime
349 + ((numBits * 1000)/kbps);
351 case IEEE80211_T_OFDM:
352 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
353 HALASSERT(bitsPerSymbol != 0);
355 numBits = OFDM_PLCP_BITS + (frameLen << 3);
356 numSymbols = howmany(numBits, bitsPerSymbol);
357 txTime = OFDM_SIFS_TIME
359 + (numSymbols * OFDM_SYMBOL_TIME);
361 case IEEE80211_T_OFDM_HALF:
362 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
363 HALASSERT(bitsPerSymbol != 0);
365 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3);
366 numSymbols = howmany(numBits, bitsPerSymbol);
367 txTime = OFDM_HALF_SIFS_TIME
368 + OFDM_HALF_PREAMBLE_TIME
369 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
371 case IEEE80211_T_OFDM_QUARTER:
372 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
373 HALASSERT(bitsPerSymbol != 0);
375 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
376 numSymbols = howmany(numBits, bitsPerSymbol);
377 txTime = OFDM_QUARTER_SIFS_TIME
378 + OFDM_QUARTER_PREAMBLE_TIME
379 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
381 case IEEE80211_T_TURBO:
382 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000;
383 HALASSERT(bitsPerSymbol != 0);
385 numBits = TURBO_PLCP_BITS + (frameLen << 3);
386 numSymbols = howmany(numBits, bitsPerSymbol);
387 txTime = TURBO_SIFS_TIME
388 + TURBO_PREAMBLE_TIME
389 + (numSymbols * TURBO_SYMBOL_TIME);
392 HALDEBUG(ah, HAL_DEBUG_PHYIO,
393 "%s: unknown phy %u (rate ix %u)\n",
394 __func__, rates->info[rateix].phy, rateix);
402 WIRELESS_MODE_11a = 0,
403 WIRELESS_MODE_TURBO = 1,
404 WIRELESS_MODE_11b = 2,
405 WIRELESS_MODE_11g = 3,
406 WIRELESS_MODE_108g = 4,
412 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
414 if (IEEE80211_IS_CHAN_B(chan))
415 return WIRELESS_MODE_11b;
416 if (IEEE80211_IS_CHAN_G(chan))
417 return WIRELESS_MODE_11g;
418 if (IEEE80211_IS_CHAN_108G(chan))
419 return WIRELESS_MODE_108g;
420 if (IEEE80211_IS_CHAN_TURBO(chan))
421 return WIRELESS_MODE_TURBO;
422 return WIRELESS_MODE_11a;
426 * Convert between microseconds and core system clocks.
428 /* 11a Turbo 11b 11g 108g */
429 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
431 #define CLOCK_FAST_RATE_5GHZ_OFDM 44
434 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
436 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
439 /* NB: ah_curchan may be null when called attach time */
440 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
441 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
442 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
443 if (IEEE80211_IS_CHAN_HT40(c))
445 } else if (c != AH_NULL) {
446 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
447 if (IEEE80211_IS_CHAN_HT40(c))
450 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
455 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
457 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
460 /* NB: ah_curchan may be null when called attach time */
461 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
462 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
463 usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM;
464 if (IEEE80211_IS_CHAN_HT40(c))
466 } else if (c != AH_NULL) {
467 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
468 if (IEEE80211_IS_CHAN_HT40(c))
471 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
476 * Setup a h/w rate table's reverse lookup table and
477 * fill in ack durations. This routine is called for
478 * each rate table returned through the ah_getRateTable
479 * method. The reverse lookup tables are assumed to be
480 * initialized to zero (or at least the first entry).
481 * We use this as a key that indicates whether or not
482 * we've previously setup the reverse lookup table.
484 * XXX not reentrant, but shouldn't matter
487 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
489 #define N(a) (sizeof(a)/sizeof(a[0]))
492 if (rt->rateCodeToIndex[0] != 0) /* already setup */
494 for (i = 0; i < N(rt->rateCodeToIndex); i++)
495 rt->rateCodeToIndex[i] = (uint8_t) -1;
496 for (i = 0; i < rt->rateCount; i++) {
497 uint8_t code = rt->info[i].rateCode;
498 uint8_t cix = rt->info[i].controlRate;
500 HALASSERT(code < N(rt->rateCodeToIndex));
501 rt->rateCodeToIndex[code] = i;
502 HALASSERT((code | rt->info[i].shortPreamble) <
503 N(rt->rateCodeToIndex));
504 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
506 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
507 * depends on whether they are marked as basic rates;
508 * the static tables are setup with an 11b-compatible
509 * 2Mb/s rate which will work but is suboptimal
511 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
512 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
513 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
514 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
520 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
521 uint32_t capability, uint32_t *result)
523 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
526 case HAL_CAP_REG_DMN: /* regulatory domain */
527 *result = AH_PRIVATE(ah)->ah_currentRD;
529 case HAL_CAP_DFS_DMN: /* DFS Domain */
530 *result = AH_PRIVATE(ah)->ah_dfsDomain;
532 case HAL_CAP_CIPHER: /* cipher handled in hardware */
533 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
535 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
537 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
538 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
539 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
541 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
543 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
544 *result = pCap->halKeyCacheSize;
546 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
547 *result = pCap->halTotalQueues;
549 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
550 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
551 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
552 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
553 case HAL_CAP_COMPRESSION:
554 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
556 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
557 case HAL_CAP_FASTFRAME:
558 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
559 case HAL_CAP_DIAG: /* hardware diagnostic support */
560 *result = AH_PRIVATE(ah)->ah_diagreg;
562 case HAL_CAP_TXPOW: /* global tx power limit */
563 switch (capability) {
564 case 0: /* facility is supported */
566 case 1: /* current limit */
567 *result = AH_PRIVATE(ah)->ah_powerLimit;
569 case 2: /* current max tx power */
570 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
572 case 3: /* scale factor */
573 *result = AH_PRIVATE(ah)->ah_tpScale;
577 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
578 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
579 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
580 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
581 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
583 case HAL_CAP_RFSILENT: /* rfsilent support */
584 switch (capability) {
585 case 0: /* facility is supported */
586 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
587 case 1: /* current setting */
588 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
589 HAL_OK : HAL_ENOTSUPP;
590 case 2: /* rfsilent config */
591 *result = AH_PRIVATE(ah)->ah_rfsilent;
599 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
601 return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
602 case HAL_CAP_FAST_CC:
603 return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
604 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
605 *result = pCap->halTxChainMask;
607 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
608 *result = pCap->halRxChainMask;
610 case HAL_CAP_NUM_GPIO_PINS:
611 *result = pCap->halNumGpioPins;
614 return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
615 case HAL_CAP_RTS_AGGR_LIMIT:
616 *result = pCap->halRtsAggrLimit;
618 case HAL_CAP_4ADDR_AGGR:
619 return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
620 case HAL_CAP_EXT_CHAN_DFS:
621 return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
622 case HAL_CAP_COMBINED_RADAR_RSSI:
623 return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
624 case HAL_CAP_AUTO_SLEEP:
625 return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
626 case HAL_CAP_MBSSID_AGGR_SUPPORT:
627 return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
628 case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */
629 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
630 case HAL_CAP_REG_FLAG:
631 *result = AH_PRIVATE(ah)->ah_currentRDext;
633 case HAL_CAP_ENHANCED_DMA_SUPPORT:
634 return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP;
635 case HAL_CAP_NUM_TXMAPS:
636 *result = pCap->halNumTxMaps;
638 case HAL_CAP_TXDESCLEN:
639 *result = pCap->halTxDescLen;
641 case HAL_CAP_TXSTATUSLEN:
642 *result = pCap->halTxStatusLen;
644 case HAL_CAP_RXSTATUSLEN:
645 *result = pCap->halRxStatusLen;
647 case HAL_CAP_RXFIFODEPTH:
648 switch (capability) {
649 case HAL_RX_QUEUE_HP:
650 *result = pCap->halRxHpFifoDepth;
652 case HAL_RX_QUEUE_LP:
653 *result = pCap->halRxLpFifoDepth;
658 case HAL_CAP_RXBUFSIZE:
659 case HAL_CAP_NUM_MR_RETRIES:
660 return HAL_EINVAL; /* XXX not yet */
661 case HAL_CAP_BT_COEX:
662 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
663 case HAL_CAP_HT20_SGI:
664 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
665 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
666 *result = pCap->halTstampPrecision;
668 case HAL_CAP_ENHANCED_DFS_SUPPORT:
669 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
671 /* FreeBSD-specific entries for now */
672 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
673 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
674 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
675 *result = pCap->halIntrMask;
677 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
678 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
679 case HAL_CAP_STREAMS: /* number of 11n spatial streams */
680 switch (capability) {
682 *result = pCap->halTxStreams;
685 *result = pCap->halRxStreams;
690 case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */
691 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
692 case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */
693 return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP;
694 case HAL_CAP_BB_READ_WAR: /* Baseband read WAR */
695 return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP;
696 case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */
697 return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP;
705 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
706 uint32_t capability, uint32_t setting, HAL_STATUS *status)
711 switch (capability) {
713 if (setting <= HAL_TP_SCALE_MIN) {
714 AH_PRIVATE(ah)->ah_tpScale = setting;
720 case HAL_CAP_RFSILENT: /* rfsilent support */
722 * NB: allow even if halRfSilentSupport is false
723 * in case the EEPROM is misprogrammed.
725 switch (capability) {
726 case 1: /* current setting */
727 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
729 case 2: /* rfsilent config */
730 /* XXX better done per-chip for validation? */
731 AH_PRIVATE(ah)->ah_rfsilent = setting;
735 case HAL_CAP_REG_DMN: /* regulatory domain */
736 AH_PRIVATE(ah)->ah_currentRD = setting;
738 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
739 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
745 *status = HAL_EINVAL;
750 * Common support for getDiagState method.
754 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
755 void *dstbuf, int space)
757 uint32_t *dp = dstbuf;
760 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
761 u_int r = regs[i].start;
762 u_int e = regs[i].end;
764 space -= sizeof(uint32_t);
766 *dp++ = OS_REG_READ(ah, r);
767 r += sizeof(uint32_t);
768 space -= sizeof(uint32_t);
769 } while (r <= e && space >= sizeof(uint32_t));
771 return (char *) dp - (char *) dstbuf;
775 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
777 while (space >= sizeof(HAL_REGWRITE)) {
778 OS_REG_WRITE(ah, regs->addr, regs->value);
779 regs++, space -= sizeof(HAL_REGWRITE);
784 ath_hal_getdiagstate(struct ath_hal *ah, int request,
785 const void *args, uint32_t argsize,
786 void **result, uint32_t *resultsize)
790 *result = &AH_PRIVATE(ah)->ah_devid;
791 *resultsize = sizeof(HAL_REVS);
794 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
796 case HAL_DIAG_SETREGS:
797 ath_hal_setregs(ah, args, argsize);
800 case HAL_DIAG_FATALERR:
801 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
802 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
804 case HAL_DIAG_EEREAD:
805 if (argsize != sizeof(uint16_t))
807 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
809 *resultsize = sizeof(uint16_t);
811 #ifdef AH_PRIVATE_DIAG
812 case HAL_DIAG_SETKEY: {
813 const HAL_DIAG_KEYVAL *dk;
815 if (argsize != sizeof(HAL_DIAG_KEYVAL))
817 dk = (const HAL_DIAG_KEYVAL *)args;
818 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
819 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
821 case HAL_DIAG_RESETKEY:
822 if (argsize != sizeof(uint16_t))
824 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
825 #ifdef AH_SUPPORT_WRITE_EEPROM
826 case HAL_DIAG_EEWRITE: {
827 const HAL_DIAG_EEVAL *ee;
828 if (argsize != sizeof(HAL_DIAG_EEVAL))
830 ee = (const HAL_DIAG_EEVAL *)args;
831 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
833 #endif /* AH_SUPPORT_WRITE_EEPROM */
834 #endif /* AH_PRIVATE_DIAG */
835 case HAL_DIAG_11NCOMPAT:
837 *resultsize = sizeof(uint32_t);
838 *((uint32_t *)(*result)) =
839 AH_PRIVATE(ah)->ah_11nCompat;
840 } else if (argsize == sizeof(uint32_t)) {
841 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
850 * Set the properties of the tx queue with the parameters
854 ath_hal_setTxQProps(struct ath_hal *ah,
855 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
859 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
860 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
861 "%s: inactive queue\n", __func__);
864 /* XXX validate parameters */
865 qi->tqi_ver = qInfo->tqi_ver;
866 qi->tqi_subtype = qInfo->tqi_subtype;
867 qi->tqi_qflags = qInfo->tqi_qflags;
868 qi->tqi_priority = qInfo->tqi_priority;
869 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
870 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
872 qi->tqi_aifs = INIT_AIFS;
873 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
874 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
875 /* make sure that the CWmin is of the form (2^n - 1) */
877 while (qi->tqi_cwmin < cw)
878 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
880 qi->tqi_cwmin = qInfo->tqi_cwmin;
881 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
882 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
883 /* make sure that the CWmax is of the form (2^n - 1) */
885 while (qi->tqi_cwmax < cw)
886 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
888 qi->tqi_cwmax = INIT_CWMAX;
889 /* Set retry limit values */
890 if (qInfo->tqi_shretry != 0)
891 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
893 qi->tqi_shretry = INIT_SH_RETRY;
894 if (qInfo->tqi_lgretry != 0)
895 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
897 qi->tqi_lgretry = INIT_LG_RETRY;
898 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
899 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
900 qi->tqi_burstTime = qInfo->tqi_burstTime;
901 qi->tqi_readyTime = qInfo->tqi_readyTime;
903 switch (qInfo->tqi_subtype) {
905 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
906 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
909 break; /* NB: silence compiler */
915 ath_hal_getTxQProps(struct ath_hal *ah,
916 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
918 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
919 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
920 "%s: inactive queue\n", __func__);
924 qInfo->tqi_qflags = qi->tqi_qflags;
925 qInfo->tqi_ver = qi->tqi_ver;
926 qInfo->tqi_subtype = qi->tqi_subtype;
927 qInfo->tqi_qflags = qi->tqi_qflags;
928 qInfo->tqi_priority = qi->tqi_priority;
929 qInfo->tqi_aifs = qi->tqi_aifs;
930 qInfo->tqi_cwmin = qi->tqi_cwmin;
931 qInfo->tqi_cwmax = qi->tqi_cwmax;
932 qInfo->tqi_shretry = qi->tqi_shretry;
933 qInfo->tqi_lgretry = qi->tqi_lgretry;
934 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
935 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
936 qInfo->tqi_burstTime = qi->tqi_burstTime;
937 qInfo->tqi_readyTime = qi->tqi_readyTime;
941 /* 11a Turbo 11b 11g 108g */
942 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
945 * Read the current channel noise floor and return.
946 * If nf cal hasn't finished, channel noise floor should be 0
947 * and we return a nominal value based on band and frequency.
949 * NB: This is a private routine used by per-chip code to
950 * implement the ah_getChanNoise method.
953 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
955 HAL_CHANNEL_INTERNAL *ichan;
957 ichan = ath_hal_checkchannel(ah, chan);
958 if (ichan == AH_NULL) {
959 HALDEBUG(ah, HAL_DEBUG_NFCAL,
960 "%s: invalid channel %u/0x%x; no mapping\n",
961 __func__, chan->ic_freq, chan->ic_flags);
964 if (ichan->rawNoiseFloor == 0) {
965 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
967 HALASSERT(mode < WIRELESS_MODE_MAX);
968 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
970 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
974 * Fetch the current setup of ctl/ext noise floor values.
976 * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
977 * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
979 * The caller must supply ctl/ext NF arrays which are at least
980 * AH_MIMO_MAX_CHAINS entries long.
983 ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
984 const struct ieee80211_channel *chan, int16_t *nf_ctl,
987 #ifdef AH_SUPPORT_AR5416
988 HAL_CHANNEL_INTERNAL *ichan;
991 ichan = ath_hal_checkchannel(ah, chan);
992 if (ichan == AH_NULL) {
993 HALDEBUG(ah, HAL_DEBUG_NFCAL,
994 "%s: invalid channel %u/0x%x; no mapping\n",
995 __func__, chan->ic_freq, chan->ic_flags);
996 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
997 nf_ctl[i] = nf_ext[i] = 0;
1002 /* Return 0 if there's no valid MIMO values (yet) */
1003 if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
1004 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
1005 nf_ctl[i] = nf_ext[i] = 0;
1009 if (ichan->rawNoiseFloor == 0) {
1010 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
1011 HALASSERT(mode < WIRELESS_MODE_MAX);
1013 * See the comment below - this could cause issues for
1014 * stations which have a very low RSSI, below the
1015 * 'normalised' NF values in NOISE_FLOOR[].
1017 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
1018 nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
1019 ath_hal_getNfAdjust(ah, ichan);
1024 * The value returned here from a MIMO radio is presumed to be
1025 * "good enough" as a NF calculation. As RSSI values are calculated
1026 * against this, an adjusted NF may be higher than the RSSI value
1027 * returned from a vary weak station, resulting in an obscenely
1028 * high signal strength calculation being returned.
1030 * This should be re-evaluated at a later date, along with any
1031 * signal strength calculations which are made. Quite likely the
1032 * RSSI values will need to be adjusted to ensure the calculations
1033 * don't "wrap" when RSSI is less than the "adjusted" NF value.
1034 * ("Adjust" here is via ichan->noiseFloorAdjust.)
1036 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) {
1037 nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
1038 nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
1044 #endif /* AH_SUPPORT_AR5416 */
1048 * Process all valid raw noise floors into the dBm noise floor values.
1049 * Though our device has no reference for a dBm noise floor, we perform
1050 * a relative minimization of NF's based on the lowest NF found across a
1054 ath_hal_process_noisefloor(struct ath_hal *ah)
1056 HAL_CHANNEL_INTERNAL *c;
1057 int16_t correct2, correct5;
1058 int16_t lowest2, lowest5;
1062 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
1063 * for statistically recorded NF/channel deviation.
1065 correct2 = lowest2 = 0;
1066 correct5 = lowest5 = 0;
1067 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1071 c = &AH_PRIVATE(ah)->ah_channels[i];
1072 if (c->rawNoiseFloor >= 0)
1074 /* XXX can't identify proper mode */
1075 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
1076 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
1077 ath_hal_getNfAdjust(ah, c);
1078 if (IS_CHAN_5GHZ(c)) {
1081 correct5 = NOISE_FLOOR[mode] -
1082 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1087 correct2 = NOISE_FLOOR[mode] -
1088 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
1093 /* Correct the channels to reach the expected NF value */
1094 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
1095 c = &AH_PRIVATE(ah)->ah_channels[i];
1096 if (c->rawNoiseFloor >= 0)
1098 /* Apply correction factor */
1099 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
1100 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
1101 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
1102 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
1107 * INI support routines.
1111 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1116 HALASSERT(col < ia->cols);
1117 for (r = 0; r < ia->rows; r++) {
1118 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
1119 HAL_INI_VAL(ia, r, col));
1121 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */
1122 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
1131 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
1135 HALASSERT(col < ia->cols);
1136 for (r = 0; r < ia->rows; r++)
1137 data[r] = HAL_INI_VAL(ia, r, col);
1141 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
1142 const uint32_t data[], int regWr)
1146 for (r = 0; r < ia->rows; r++) {
1147 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
1154 * These are EEPROM board related routines which should likely live in
1155 * a helper library of some sort.
1158 /**************************************************************
1159 * ath_ee_getLowerUppderIndex
1161 * Return indices surrounding the value in sorted integer lists.
1162 * Requirement: the input list must be monotonically increasing
1163 * and populated up to the list size
1164 * Returns: match is set if an index in the array matches exactly
1165 * or a the target is before or after the range of the array.
1168 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
1169 uint16_t *indexL, uint16_t *indexR)
1174 * Check first and last elements for beyond ordered array cases.
1176 if (target <= pList[0]) {
1177 *indexL = *indexR = 0;
1180 if (target >= pList[listSize-1]) {
1181 *indexL = *indexR = (uint16_t)(listSize - 1);
1185 /* look for value being near or between 2 values in list */
1186 for (i = 0; i < listSize - 1; i++) {
1188 * If value is close to the current value of the list
1189 * then target is not between values, it is one of the values
1191 if (pList[i] == target) {
1192 *indexL = *indexR = i;
1196 * Look for value being between current value and next value
1197 * if so return these 2 values
1199 if (target < pList[i + 1]) {
1201 *indexR = (uint16_t)(i + 1);
1206 *indexL = *indexR = 0;
1210 /**************************************************************
1211 * ath_ee_FillVpdTable
1213 * Fill the Vpdlist for indices Pmax-Pmin
1214 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
1217 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
1218 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
1221 uint8_t currPwr = pwrMin;
1222 uint16_t idxL, idxR;
1224 HALASSERT(pwrMax > pwrMin);
1225 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
1226 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
1229 idxR = 1; /* extrapolate below */
1230 if (idxL == numIntercepts - 1)
1231 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */
1232 if (pPwrList[idxL] == pPwrList[idxR])
1235 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
1236 (pPwrList[idxR] - pPwrList[idxL]) );
1238 pRetVpdList[i] = (uint8_t)k;
1239 currPwr += 2; /* half dB steps */
1245 /**************************************************************************
1246 * ath_ee_interpolate
1248 * Returns signed interpolated or the scaled up interpolated value
1251 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
1252 int16_t targetLeft, int16_t targetRight)
1256 if (srcRight == srcLeft) {
1259 rv = (int16_t)( ((target - srcLeft) * targetRight +
1260 (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
1269 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
1271 /* XXX handle wrap/overflow */
1272 OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
1276 * Enable or disable CCA.
1279 ath_hal_setcca(struct ath_hal *ah, int ena)
1282 * NB: fill me in; this is not provided by default because disabling
1283 * CCA in most locales violates regulatory.
1291 ath_hal_getcca(struct ath_hal *ah)
1294 if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
1296 return ((diag & 0x500000) == 0);
1300 * This routine is only needed when supporting EEPROM-in-RAM setups
1301 * (eg embedded SoCs and on-board PCI/PCIe devices.)
1303 /* NB: This is in 16 bit words; not bytes */
1304 /* XXX This doesn't belong here! */
1305 #define ATH_DATA_EEPROM_SIZE 2048
1308 ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data)
1310 if (ah->ah_eepromdata == AH_NULL) {
1311 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__);
1314 if (off > ATH_DATA_EEPROM_SIZE) {
1315 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n",
1316 __func__, off, ATH_DATA_EEPROM_SIZE);
1319 (*data) = ah->ah_eepromdata[off];