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.
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ah.c 196970 2009-09-08 13:19:05Z phk $
23 #include "ah_internal.h"
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, 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, 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_SOWL:
114 case AR_XSREV_VERSION_MERLIN:
116 case AR_XSREV_VERSION_KITE:
123 * Return the mask of available modes based on the hardware capabilities.
126 ath_hal_getwirelessmodes(struct ath_hal*ah)
128 return ath_hal_getWirelessModes(ah);
131 /* linker set of registered RF backends */
132 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
135 * Check the set of registered RF backends to see if
136 * any recognize the device as one they can support.
139 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
141 struct ath_hal_rf * const *prf;
143 OS_SET_FOREACH(prf, ah_rfs) {
144 struct ath_hal_rf *rf = *prf;
148 *ecode = HAL_ENOTSUPP;
153 ath_hal_rf_name(struct ath_hal *ah)
155 switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
157 return "5110"; /* NB: made up */
158 case AR_RAD5111_SREV_MAJOR:
159 case AR_RAD5111_SREV_PROD:
161 case AR_RAD2111_SREV_MAJOR:
163 case AR_RAD5112_SREV_MAJOR:
164 case AR_RAD5112_SREV_2_0:
165 case AR_RAD5112_SREV_2_1:
167 case AR_RAD2112_SREV_MAJOR:
168 case AR_RAD2112_SREV_2_0:
169 case AR_RAD2112_SREV_2_1:
171 case AR_RAD2413_SREV_MAJOR:
173 case AR_RAD5413_SREV_MAJOR:
175 case AR_RAD2316_SREV_MAJOR:
177 case AR_RAD2317_SREV_MAJOR:
179 case AR_RAD5424_SREV_MAJOR:
182 case AR_RAD5133_SREV_MAJOR:
184 case AR_RAD2133_SREV_MAJOR:
186 case AR_RAD5122_SREV_MAJOR:
188 case AR_RAD2122_SREV_MAJOR:
195 * Poll the register looking for a specific value.
198 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
200 #define AH_TIMEOUT 1000
203 for (i = 0; i < AH_TIMEOUT; i++) {
204 if ((OS_REG_READ(ah, reg) & mask) == val)
208 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
209 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
210 __func__, reg, OS_REG_READ(ah, reg), mask, val);
216 * Reverse the bits starting at the low bit for a value of
220 ath_hal_reverseBits(uint32_t val, uint32_t n)
225 for (i = 0, retval = 0; i < n; i++) {
226 retval = (retval << 1) | (val & 1);
233 * Compute the time to transmit a frame of length frameLen bytes
234 * using the specified rate, phy, and short preamble setting.
237 ath_hal_computetxtime(struct ath_hal *ah,
238 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
239 HAL_BOOL shortPreamble)
241 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
244 kbps = rates->info[rateix].rateKbps;
246 * index can be invalid duting dynamic Turbo transitions.
251 switch (rates->info[rateix].phy) {
252 case IEEE80211_T_CCK:
253 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
254 if (shortPreamble && rates->info[rateix].shortPreamble)
256 numBits = frameLen << 3;
257 txTime = CCK_SIFS_TIME + phyTime
258 + ((numBits * 1000)/kbps);
260 case IEEE80211_T_OFDM:
261 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
262 HALASSERT(bitsPerSymbol != 0);
264 numBits = OFDM_PLCP_BITS + (frameLen << 3);
265 numSymbols = howmany(numBits, bitsPerSymbol);
266 txTime = OFDM_SIFS_TIME
268 + (numSymbols * OFDM_SYMBOL_TIME);
270 case IEEE80211_T_OFDM_HALF:
271 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
272 HALASSERT(bitsPerSymbol != 0);
274 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3);
275 numSymbols = howmany(numBits, bitsPerSymbol);
276 txTime = OFDM_HALF_SIFS_TIME
277 + OFDM_HALF_PREAMBLE_TIME
278 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
280 case IEEE80211_T_OFDM_QUARTER:
281 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
282 HALASSERT(bitsPerSymbol != 0);
284 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
285 numSymbols = howmany(numBits, bitsPerSymbol);
286 txTime = OFDM_QUARTER_SIFS_TIME
287 + OFDM_QUARTER_PREAMBLE_TIME
288 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
290 case IEEE80211_T_TURBO:
291 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000;
292 HALASSERT(bitsPerSymbol != 0);
294 numBits = TURBO_PLCP_BITS + (frameLen << 3);
295 numSymbols = howmany(numBits, bitsPerSymbol);
296 txTime = TURBO_SIFS_TIME
297 + TURBO_PREAMBLE_TIME
298 + (numSymbols * TURBO_SYMBOL_TIME);
301 HALDEBUG(ah, HAL_DEBUG_PHYIO,
302 "%s: unknown phy %u (rate ix %u)\n",
303 __func__, rates->info[rateix].phy, rateix);
311 WIRELESS_MODE_11a = 0,
312 WIRELESS_MODE_TURBO = 1,
313 WIRELESS_MODE_11b = 2,
314 WIRELESS_MODE_11g = 3,
315 WIRELESS_MODE_108g = 4,
321 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
323 if (IEEE80211_IS_CHAN_B(chan))
324 return WIRELESS_MODE_11b;
325 if (IEEE80211_IS_CHAN_G(chan))
326 return WIRELESS_MODE_11g;
327 if (IEEE80211_IS_CHAN_108G(chan))
328 return WIRELESS_MODE_108g;
329 if (IEEE80211_IS_CHAN_TURBO(chan))
330 return WIRELESS_MODE_TURBO;
331 return WIRELESS_MODE_11a;
335 * Convert between microseconds and core system clocks.
337 /* 11a Turbo 11b 11g 108g */
338 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
341 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
343 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
346 /* NB: ah_curchan may be null when called attach time */
348 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
349 if (IEEE80211_IS_CHAN_HT40(c))
352 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
357 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
359 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
362 /* NB: ah_curchan may be null when called attach time */
364 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
365 if (IEEE80211_IS_CHAN_HT40(c))
368 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
373 * Setup a h/w rate table's reverse lookup table and
374 * fill in ack durations. This routine is called for
375 * each rate table returned through the ah_getRateTable
376 * method. The reverse lookup tables are assumed to be
377 * initialized to zero (or at least the first entry).
378 * We use this as a key that indicates whether or not
379 * we've previously setup the reverse lookup table.
381 * XXX not reentrant, but shouldn't matter
384 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
386 #define N(a) (sizeof(a)/sizeof(a[0]))
389 if (rt->rateCodeToIndex[0] != 0) /* already setup */
391 for (i = 0; i < N(rt->rateCodeToIndex); i++)
392 rt->rateCodeToIndex[i] = (uint8_t) -1;
393 for (i = 0; i < rt->rateCount; i++) {
394 uint8_t code = rt->info[i].rateCode;
395 uint8_t cix = rt->info[i].controlRate;
397 HALASSERT(code < N(rt->rateCodeToIndex));
398 rt->rateCodeToIndex[code] = i;
399 HALASSERT((code | rt->info[i].shortPreamble) <
400 N(rt->rateCodeToIndex));
401 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
403 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
404 * depends on whether they are marked as basic rates;
405 * the static tables are setup with an 11b-compatible
406 * 2Mb/s rate which will work but is suboptimal
408 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
409 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
410 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
411 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
417 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
418 uint32_t capability, uint32_t *result)
420 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
423 case HAL_CAP_REG_DMN: /* regulatory domain */
424 *result = AH_PRIVATE(ah)->ah_currentRD;
426 case HAL_CAP_CIPHER: /* cipher handled in hardware */
427 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
429 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
431 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
432 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
433 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
435 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
437 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
438 *result = pCap->halKeyCacheSize;
440 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
441 *result = pCap->halTotalQueues;
443 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
444 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
445 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
446 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
447 case HAL_CAP_COMPRESSION:
448 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
450 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
451 case HAL_CAP_FASTFRAME:
452 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
453 case HAL_CAP_DIAG: /* hardware diagnostic support */
454 *result = AH_PRIVATE(ah)->ah_diagreg;
456 case HAL_CAP_TXPOW: /* global tx power limit */
457 switch (capability) {
458 case 0: /* facility is supported */
460 case 1: /* current limit */
461 *result = AH_PRIVATE(ah)->ah_powerLimit;
463 case 2: /* current max tx power */
464 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
466 case 3: /* scale factor */
467 *result = AH_PRIVATE(ah)->ah_tpScale;
471 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
472 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
473 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
474 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
475 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
477 case HAL_CAP_RFSILENT: /* rfsilent support */
478 switch (capability) {
479 case 0: /* facility is supported */
480 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
481 case 1: /* current setting */
482 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
483 HAL_OK : HAL_ENOTSUPP;
484 case 2: /* rfsilent config */
485 *result = AH_PRIVATE(ah)->ah_rfsilent;
491 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
492 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
494 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
495 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
496 *result = pCap->halTxChainMask;
498 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
499 *result = pCap->halRxChainMask;
501 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
502 *result = pCap->halTstampPrecision;
504 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
505 *result = pCap->halIntrMask;
507 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
508 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
515 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
516 uint32_t capability, uint32_t setting, HAL_STATUS *status)
521 switch (capability) {
523 if (setting <= HAL_TP_SCALE_MIN) {
524 AH_PRIVATE(ah)->ah_tpScale = setting;
530 case HAL_CAP_RFSILENT: /* rfsilent support */
532 * NB: allow even if halRfSilentSupport is false
533 * in case the EEPROM is misprogrammed.
535 switch (capability) {
536 case 1: /* current setting */
537 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
539 case 2: /* rfsilent config */
540 /* XXX better done per-chip for validation? */
541 AH_PRIVATE(ah)->ah_rfsilent = setting;
545 case HAL_CAP_REG_DMN: /* regulatory domain */
546 AH_PRIVATE(ah)->ah_currentRD = setting;
548 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
549 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
555 *status = HAL_EINVAL;
560 * Common support for getDiagState method.
564 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
565 void *dstbuf, int space)
567 uint32_t *dp = dstbuf;
570 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
571 u_int r = regs[i].start;
572 u_int e = regs[i].end;
574 space -= sizeof(uint32_t);
576 *dp++ = OS_REG_READ(ah, r);
577 r += sizeof(uint32_t);
578 space -= sizeof(uint32_t);
579 } while (r <= e && space >= sizeof(uint32_t));
581 return (char *) dp - (char *) dstbuf;
585 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
587 while (space >= sizeof(HAL_REGWRITE)) {
588 OS_REG_WRITE(ah, regs->addr, regs->value);
589 regs++, space -= sizeof(HAL_REGWRITE);
594 ath_hal_getdiagstate(struct ath_hal *ah, int request,
595 const void *args, uint32_t argsize,
596 void **result, uint32_t *resultsize)
600 *result = &AH_PRIVATE(ah)->ah_devid;
601 *resultsize = sizeof(HAL_REVS);
604 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
606 case HAL_DIAG_SETREGS:
607 ath_hal_setregs(ah, args, argsize);
610 case HAL_DIAG_FATALERR:
611 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
612 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
614 case HAL_DIAG_EEREAD:
615 if (argsize != sizeof(uint16_t))
617 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
619 *resultsize = sizeof(uint16_t);
621 #ifdef AH_PRIVATE_DIAG
622 case HAL_DIAG_SETKEY: {
623 const HAL_DIAG_KEYVAL *dk;
625 if (argsize != sizeof(HAL_DIAG_KEYVAL))
627 dk = (const HAL_DIAG_KEYVAL *)args;
628 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
629 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
631 case HAL_DIAG_RESETKEY:
632 if (argsize != sizeof(uint16_t))
634 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
635 #ifdef AH_SUPPORT_WRITE_EEPROM
636 case HAL_DIAG_EEWRITE: {
637 const HAL_DIAG_EEVAL *ee;
638 if (argsize != sizeof(HAL_DIAG_EEVAL))
640 ee = (const HAL_DIAG_EEVAL *)args;
641 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
643 #endif /* AH_SUPPORT_WRITE_EEPROM */
644 #endif /* AH_PRIVATE_DIAG */
645 case HAL_DIAG_11NCOMPAT:
647 *resultsize = sizeof(uint32_t);
648 *((uint32_t *)(*result)) =
649 AH_PRIVATE(ah)->ah_11nCompat;
650 } else if (argsize == sizeof(uint32_t)) {
651 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
660 * Set the properties of the tx queue with the parameters
664 ath_hal_setTxQProps(struct ath_hal *ah,
665 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
669 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
670 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
671 "%s: inactive queue\n", __func__);
674 /* XXX validate parameters */
675 qi->tqi_ver = qInfo->tqi_ver;
676 qi->tqi_subtype = qInfo->tqi_subtype;
677 qi->tqi_qflags = qInfo->tqi_qflags;
678 qi->tqi_priority = qInfo->tqi_priority;
679 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
680 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
682 qi->tqi_aifs = INIT_AIFS;
683 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
684 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
685 /* make sure that the CWmin is of the form (2^n - 1) */
687 while (qi->tqi_cwmin < cw)
688 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
690 qi->tqi_cwmin = qInfo->tqi_cwmin;
691 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
692 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
693 /* make sure that the CWmax is of the form (2^n - 1) */
695 while (qi->tqi_cwmax < cw)
696 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
698 qi->tqi_cwmax = INIT_CWMAX;
699 /* Set retry limit values */
700 if (qInfo->tqi_shretry != 0)
701 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
703 qi->tqi_shretry = INIT_SH_RETRY;
704 if (qInfo->tqi_lgretry != 0)
705 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
707 qi->tqi_lgretry = INIT_LG_RETRY;
708 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
709 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
710 qi->tqi_burstTime = qInfo->tqi_burstTime;
711 qi->tqi_readyTime = qInfo->tqi_readyTime;
713 switch (qInfo->tqi_subtype) {
715 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
716 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
719 break; /* NB: silence compiler */
725 ath_hal_getTxQProps(struct ath_hal *ah,
726 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
728 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
729 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
730 "%s: inactive queue\n", __func__);
734 qInfo->tqi_qflags = qi->tqi_qflags;
735 qInfo->tqi_ver = qi->tqi_ver;
736 qInfo->tqi_subtype = qi->tqi_subtype;
737 qInfo->tqi_qflags = qi->tqi_qflags;
738 qInfo->tqi_priority = qi->tqi_priority;
739 qInfo->tqi_aifs = qi->tqi_aifs;
740 qInfo->tqi_cwmin = qi->tqi_cwmin;
741 qInfo->tqi_cwmax = qi->tqi_cwmax;
742 qInfo->tqi_shretry = qi->tqi_shretry;
743 qInfo->tqi_lgretry = qi->tqi_lgretry;
744 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
745 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
746 qInfo->tqi_burstTime = qi->tqi_burstTime;
747 qInfo->tqi_readyTime = qi->tqi_readyTime;
751 /* 11a Turbo 11b 11g 108g */
752 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
755 * Read the current channel noise floor and return.
756 * If nf cal hasn't finished, channel noise floor should be 0
757 * and we return a nominal value based on band and frequency.
759 * NB: This is a private routine used by per-chip code to
760 * implement the ah_getChanNoise method.
763 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
765 HAL_CHANNEL_INTERNAL *ichan;
767 ichan = ath_hal_checkchannel(ah, chan);
768 if (ichan == AH_NULL) {
769 HALDEBUG(ah, HAL_DEBUG_NFCAL,
770 "%s: invalid channel %u/0x%x; no mapping\n",
771 __func__, chan->ic_freq, chan->ic_flags);
774 if (ichan->rawNoiseFloor == 0) {
775 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
777 HALASSERT(mode < WIRELESS_MODE_MAX);
778 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
780 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
784 * Process all valid raw noise floors into the dBm noise floor values.
785 * Though our device has no reference for a dBm noise floor, we perform
786 * a relative minimization of NF's based on the lowest NF found across a
790 ath_hal_process_noisefloor(struct ath_hal *ah)
792 HAL_CHANNEL_INTERNAL *c;
793 int16_t correct2, correct5;
794 int16_t lowest2, lowest5;
798 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
799 * for statistically recorded NF/channel deviation.
801 correct2 = lowest2 = 0;
802 correct5 = lowest5 = 0;
803 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
807 c = &AH_PRIVATE(ah)->ah_channels[i];
808 if (c->rawNoiseFloor >= 0)
810 /* XXX can't identify proper mode */
811 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
812 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
813 ath_hal_getNfAdjust(ah, c);
814 if (IS_CHAN_5GHZ(c)) {
817 correct5 = NOISE_FLOOR[mode] -
818 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
823 correct2 = NOISE_FLOOR[mode] -
824 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
829 /* Correct the channels to reach the expected NF value */
830 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
831 c = &AH_PRIVATE(ah)->ah_channels[i];
832 if (c->rawNoiseFloor >= 0)
834 /* Apply correction factor */
835 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
836 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
837 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
838 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
843 * INI support routines.
847 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
852 HALASSERT(col < ia->cols);
853 for (r = 0; r < ia->rows; r++) {
854 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
855 HAL_INI_VAL(ia, r, col));
862 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
866 HALASSERT(col < ia->cols);
867 for (r = 0; r < ia->rows; r++)
868 data[r] = HAL_INI_VAL(ia, r, col);
872 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
873 const uint32_t data[], int regWr)
877 for (r = 0; r < ia->rows; r++) {
878 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);