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)
388 if (rt->rateCodeToIndex[0] != 0) /* already setup */
390 for (i = 0; i < NELEM(rt->rateCodeToIndex); i++)
391 rt->rateCodeToIndex[i] = (uint8_t) -1;
392 for (i = 0; i < rt->rateCount; i++) {
393 uint8_t code = rt->info[i].rateCode;
394 uint8_t cix = rt->info[i].controlRate;
396 HALASSERT(code < NELEM(rt->rateCodeToIndex));
397 rt->rateCodeToIndex[code] = i;
398 HALASSERT((code | rt->info[i].shortPreamble) <
399 NELEM(rt->rateCodeToIndex));
400 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
402 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
403 * depends on whether they are marked as basic rates;
404 * the static tables are setup with an 11b-compatible
405 * 2Mb/s rate which will work but is suboptimal
407 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
408 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
409 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
410 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
415 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
416 uint32_t capability, uint32_t *result)
418 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
421 case HAL_CAP_REG_DMN: /* regulatory domain */
422 *result = AH_PRIVATE(ah)->ah_currentRD;
424 case HAL_CAP_CIPHER: /* cipher handled in hardware */
425 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
427 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
429 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
430 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
431 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
433 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
435 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
436 *result = pCap->halKeyCacheSize;
438 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
439 *result = pCap->halTotalQueues;
441 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
442 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
443 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
444 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
445 case HAL_CAP_COMPRESSION:
446 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
448 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
449 case HAL_CAP_FASTFRAME:
450 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
451 case HAL_CAP_DIAG: /* hardware diagnostic support */
452 *result = AH_PRIVATE(ah)->ah_diagreg;
454 case HAL_CAP_TXPOW: /* global tx power limit */
455 switch (capability) {
456 case 0: /* facility is supported */
458 case 1: /* current limit */
459 *result = AH_PRIVATE(ah)->ah_powerLimit;
461 case 2: /* current max tx power */
462 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
464 case 3: /* scale factor */
465 *result = AH_PRIVATE(ah)->ah_tpScale;
469 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
470 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
471 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
472 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
473 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
475 case HAL_CAP_RFSILENT: /* rfsilent support */
476 switch (capability) {
477 case 0: /* facility is supported */
478 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
479 case 1: /* current setting */
480 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
481 HAL_OK : HAL_ENOTSUPP;
482 case 2: /* rfsilent config */
483 *result = AH_PRIVATE(ah)->ah_rfsilent;
489 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
490 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
492 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
493 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
494 *result = pCap->halTxChainMask;
496 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
497 *result = pCap->halRxChainMask;
499 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
500 *result = pCap->halTstampPrecision;
502 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
503 *result = pCap->halIntrMask;
505 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
506 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
513 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
514 uint32_t capability, uint32_t setting, HAL_STATUS *status)
519 switch (capability) {
521 if (setting <= HAL_TP_SCALE_MIN) {
522 AH_PRIVATE(ah)->ah_tpScale = setting;
528 case HAL_CAP_RFSILENT: /* rfsilent support */
530 * NB: allow even if halRfSilentSupport is false
531 * in case the EEPROM is misprogrammed.
533 switch (capability) {
534 case 1: /* current setting */
535 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
537 case 2: /* rfsilent config */
538 /* XXX better done per-chip for validation? */
539 AH_PRIVATE(ah)->ah_rfsilent = setting;
543 case HAL_CAP_REG_DMN: /* regulatory domain */
544 AH_PRIVATE(ah)->ah_currentRD = setting;
546 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
547 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
553 *status = HAL_EINVAL;
558 * Common support for getDiagState method.
562 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
563 void *dstbuf, int space)
565 uint32_t *dp = dstbuf;
568 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
569 u_int r = regs[i].start;
570 u_int e = regs[i].end;
572 space -= sizeof(uint32_t);
574 *dp++ = OS_REG_READ(ah, r);
575 r += sizeof(uint32_t);
576 space -= sizeof(uint32_t);
577 } while (r <= e && space >= sizeof(uint32_t));
579 return (char *) dp - (char *) dstbuf;
583 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
585 while (space >= sizeof(HAL_REGWRITE)) {
586 OS_REG_WRITE(ah, regs->addr, regs->value);
587 regs++, space -= sizeof(HAL_REGWRITE);
592 ath_hal_getdiagstate(struct ath_hal *ah, int request,
593 const void *args, uint32_t argsize,
594 void **result, uint32_t *resultsize)
598 *result = &AH_PRIVATE(ah)->ah_devid;
599 *resultsize = sizeof(HAL_REVS);
602 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
604 case HAL_DIAG_SETREGS:
605 ath_hal_setregs(ah, args, argsize);
608 case HAL_DIAG_FATALERR:
609 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
610 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
612 case HAL_DIAG_EEREAD:
613 if (argsize != sizeof(uint16_t))
615 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
617 *resultsize = sizeof(uint16_t);
619 #ifdef AH_PRIVATE_DIAG
620 case HAL_DIAG_SETKEY: {
621 const HAL_DIAG_KEYVAL *dk;
623 if (argsize != sizeof(HAL_DIAG_KEYVAL))
625 dk = (const HAL_DIAG_KEYVAL *)args;
626 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
627 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
629 case HAL_DIAG_RESETKEY:
630 if (argsize != sizeof(uint16_t))
632 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
633 #ifdef AH_SUPPORT_WRITE_EEPROM
634 case HAL_DIAG_EEWRITE: {
635 const HAL_DIAG_EEVAL *ee;
636 if (argsize != sizeof(HAL_DIAG_EEVAL))
638 ee = (const HAL_DIAG_EEVAL *)args;
639 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
641 #endif /* AH_SUPPORT_WRITE_EEPROM */
642 #endif /* AH_PRIVATE_DIAG */
643 case HAL_DIAG_11NCOMPAT:
645 *resultsize = sizeof(uint32_t);
646 *((uint32_t *)(*result)) =
647 AH_PRIVATE(ah)->ah_11nCompat;
648 } else if (argsize == sizeof(uint32_t)) {
649 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
658 * Set the properties of the tx queue with the parameters
662 ath_hal_setTxQProps(struct ath_hal *ah,
663 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
667 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
668 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
669 "%s: inactive queue\n", __func__);
672 /* XXX validate parameters */
673 qi->tqi_ver = qInfo->tqi_ver;
674 qi->tqi_subtype = qInfo->tqi_subtype;
675 qi->tqi_qflags = qInfo->tqi_qflags;
676 qi->tqi_priority = qInfo->tqi_priority;
677 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
678 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
680 qi->tqi_aifs = INIT_AIFS;
681 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
682 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
683 /* make sure that the CWmin is of the form (2^n - 1) */
685 while (qi->tqi_cwmin < cw)
686 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
688 qi->tqi_cwmin = qInfo->tqi_cwmin;
689 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
690 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
691 /* make sure that the CWmax is of the form (2^n - 1) */
693 while (qi->tqi_cwmax < cw)
694 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
696 qi->tqi_cwmax = INIT_CWMAX;
697 /* Set retry limit values */
698 if (qInfo->tqi_shretry != 0)
699 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
701 qi->tqi_shretry = INIT_SH_RETRY;
702 if (qInfo->tqi_lgretry != 0)
703 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
705 qi->tqi_lgretry = INIT_LG_RETRY;
706 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
707 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
708 qi->tqi_burstTime = qInfo->tqi_burstTime;
709 qi->tqi_readyTime = qInfo->tqi_readyTime;
711 switch (qInfo->tqi_subtype) {
713 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
714 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
717 break; /* NB: silence compiler */
723 ath_hal_getTxQProps(struct ath_hal *ah,
724 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
726 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
727 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
728 "%s: inactive queue\n", __func__);
732 qInfo->tqi_qflags = qi->tqi_qflags;
733 qInfo->tqi_ver = qi->tqi_ver;
734 qInfo->tqi_subtype = qi->tqi_subtype;
735 qInfo->tqi_qflags = qi->tqi_qflags;
736 qInfo->tqi_priority = qi->tqi_priority;
737 qInfo->tqi_aifs = qi->tqi_aifs;
738 qInfo->tqi_cwmin = qi->tqi_cwmin;
739 qInfo->tqi_cwmax = qi->tqi_cwmax;
740 qInfo->tqi_shretry = qi->tqi_shretry;
741 qInfo->tqi_lgretry = qi->tqi_lgretry;
742 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
743 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
744 qInfo->tqi_burstTime = qi->tqi_burstTime;
745 qInfo->tqi_readyTime = qi->tqi_readyTime;
749 /* 11a Turbo 11b 11g 108g */
750 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
753 * Read the current channel noise floor and return.
754 * If nf cal hasn't finished, channel noise floor should be 0
755 * and we return a nominal value based on band and frequency.
757 * NB: This is a private routine used by per-chip code to
758 * implement the ah_getChanNoise method.
761 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
763 HAL_CHANNEL_INTERNAL *ichan;
765 ichan = ath_hal_checkchannel(ah, chan);
766 if (ichan == AH_NULL) {
767 HALDEBUG(ah, HAL_DEBUG_NFCAL,
768 "%s: invalid channel %u/0x%x; no mapping\n",
769 __func__, chan->ic_freq, chan->ic_flags);
772 if (ichan->rawNoiseFloor == 0) {
773 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
775 HALASSERT(mode < WIRELESS_MODE_MAX);
776 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
778 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
782 * Process all valid raw noise floors into the dBm noise floor values.
783 * Though our device has no reference for a dBm noise floor, we perform
784 * a relative minimization of NF's based on the lowest NF found across a
788 ath_hal_process_noisefloor(struct ath_hal *ah)
790 HAL_CHANNEL_INTERNAL *c;
791 int16_t correct2, correct5;
792 int16_t lowest2, lowest5;
796 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
797 * for statistically recorded NF/channel deviation.
799 correct2 = lowest2 = 0;
800 correct5 = lowest5 = 0;
801 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
805 c = &AH_PRIVATE(ah)->ah_channels[i];
806 if (c->rawNoiseFloor >= 0)
808 /* XXX can't identify proper mode */
809 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
810 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
811 ath_hal_getNfAdjust(ah, c);
812 if (IS_CHAN_5GHZ(c)) {
815 correct5 = NOISE_FLOOR[mode] -
816 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
821 correct2 = NOISE_FLOOR[mode] -
822 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
827 /* Correct the channels to reach the expected NF value */
828 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
829 c = &AH_PRIVATE(ah)->ah_channels[i];
830 if (c->rawNoiseFloor >= 0)
832 /* Apply correction factor */
833 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
834 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
835 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
836 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
841 * INI support routines.
845 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
850 HALASSERT(col < ia->cols);
851 for (r = 0; r < ia->rows; r++) {
852 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
853 HAL_INI_VAL(ia, r, col));
860 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
864 HALASSERT(col < ia->cols);
865 for (r = 0; r < ia->rows; r++)
866 data[r] = HAL_INI_VAL(ia, r, col);
870 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
871 const uint32_t data[], int regWr)
875 for (r = 0; r < ia->rows; r++) {
876 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);