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"
25 #include "ar5416/ar5416reg.h" /* NB: includes ar5212reg.h */
27 /* linker set of registered chips */
28 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
31 * Check the set of registered chips to see if any recognize
32 * the device as one they can support.
35 ath_hal_probe(uint16_t vendorid, uint16_t devid)
37 struct ath_hal_chip * const *pchip;
39 OS_SET_FOREACH(pchip, ah_chips) {
40 const char *name = (*pchip)->probe(vendorid, devid);
48 * Attach detects device chip revisions, initializes the hwLayer
49 * function list, reads EEPROM information,
50 * selects reset vectors, and performs a short self test.
51 * Any failures will return an error that should cause a hardware
55 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
56 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
58 struct ath_hal_chip * const *pchip;
60 OS_SET_FOREACH(pchip, ah_chips) {
61 struct ath_hal_chip *chip = *pchip;
64 /* XXX don't have vendorid, assume atheros one works */
65 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
67 ah = chip->attach(devid, sc, st, sh, error);
69 /* copy back private state to public area */
70 ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
71 ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
72 ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
73 ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
74 ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
75 ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
76 ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
84 ath_hal_mac_name(struct ath_hal *ah)
86 switch (ah->ah_macVersion) {
87 case AR_SREV_VERSION_CRETE:
88 case AR_SREV_VERSION_MAUI_1:
90 case AR_SREV_VERSION_MAUI_2:
91 case AR_SREV_VERSION_OAHU:
93 case AR_SREV_VERSION_VENICE:
95 case AR_SREV_VERSION_GRIFFIN:
97 case AR_SREV_VERSION_CONDOR:
99 case AR_SREV_VERSION_EAGLE:
101 case AR_SREV_VERSION_COBRA:
107 case AR_XSREV_VERSION_OWL_PCI:
109 case AR_XSREV_VERSION_OWL_PCIE:
111 case AR_XSREV_VERSION_SOWL:
113 case AR_XSREV_VERSION_MERLIN:
115 case AR_XSREV_VERSION_KITE:
122 * Return the mask of available modes based on the hardware capabilities.
125 ath_hal_getwirelessmodes(struct ath_hal*ah)
127 return ath_hal_getWirelessModes(ah);
130 /* linker set of registered RF backends */
131 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
134 * Check the set of registered RF backends to see if
135 * any recognize the device as one they can support.
138 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
140 struct ath_hal_rf * const *prf;
142 OS_SET_FOREACH(prf, ah_rfs) {
143 struct ath_hal_rf *rf = *prf;
147 *ecode = HAL_ENOTSUPP;
152 ath_hal_rf_name(struct ath_hal *ah)
154 switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
156 return "5110"; /* NB: made up */
157 case AR_RAD5111_SREV_MAJOR:
158 case AR_RAD5111_SREV_PROD:
160 case AR_RAD2111_SREV_MAJOR:
162 case AR_RAD5112_SREV_MAJOR:
163 case AR_RAD5112_SREV_2_0:
164 case AR_RAD5112_SREV_2_1:
166 case AR_RAD2112_SREV_MAJOR:
167 case AR_RAD2112_SREV_2_0:
168 case AR_RAD2112_SREV_2_1:
170 case AR_RAD2413_SREV_MAJOR:
172 case AR_RAD5413_SREV_MAJOR:
174 case AR_RAD2316_SREV_MAJOR:
176 case AR_RAD2317_SREV_MAJOR:
178 case AR_RAD5424_SREV_MAJOR:
181 case AR_RAD5133_SREV_MAJOR:
183 case AR_RAD2133_SREV_MAJOR:
185 case AR_RAD5122_SREV_MAJOR:
187 case AR_RAD2122_SREV_MAJOR:
194 * Poll the register looking for a specific value.
197 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
199 #define AH_TIMEOUT 1000
202 for (i = 0; i < AH_TIMEOUT; i++) {
203 if ((OS_REG_READ(ah, reg) & mask) == val)
207 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
208 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
209 __func__, reg, OS_REG_READ(ah, reg), mask, val);
215 * Reverse the bits starting at the low bit for a value of
219 ath_hal_reverseBits(uint32_t val, uint32_t n)
224 for (i = 0, retval = 0; i < n; i++) {
225 retval = (retval << 1) | (val & 1);
232 * Compute the time to transmit a frame of length frameLen bytes
233 * using the specified rate, phy, and short preamble setting.
236 ath_hal_computetxtime(struct ath_hal *ah,
237 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
238 HAL_BOOL shortPreamble)
240 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
243 kbps = rates->info[rateix].rateKbps;
245 * index can be invalid duting dynamic Turbo transitions.
250 switch (rates->info[rateix].phy) {
251 case IEEE80211_T_CCK:
252 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
253 if (shortPreamble && rates->info[rateix].shortPreamble)
255 numBits = frameLen << 3;
256 txTime = CCK_SIFS_TIME + phyTime
257 + ((numBits * 1000)/kbps);
259 case IEEE80211_T_OFDM:
260 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
261 HALASSERT(bitsPerSymbol != 0);
263 numBits = OFDM_PLCP_BITS + (frameLen << 3);
264 numSymbols = howmany(numBits, bitsPerSymbol);
265 txTime = OFDM_SIFS_TIME
267 + (numSymbols * OFDM_SYMBOL_TIME);
269 case IEEE80211_T_OFDM_HALF:
270 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
271 HALASSERT(bitsPerSymbol != 0);
273 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3);
274 numSymbols = howmany(numBits, bitsPerSymbol);
275 txTime = OFDM_HALF_SIFS_TIME
276 + OFDM_HALF_PREAMBLE_TIME
277 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
279 case IEEE80211_T_OFDM_QUARTER:
280 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
281 HALASSERT(bitsPerSymbol != 0);
283 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
284 numSymbols = howmany(numBits, bitsPerSymbol);
285 txTime = OFDM_QUARTER_SIFS_TIME
286 + OFDM_QUARTER_PREAMBLE_TIME
287 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
289 case IEEE80211_T_TURBO:
290 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000;
291 HALASSERT(bitsPerSymbol != 0);
293 numBits = TURBO_PLCP_BITS + (frameLen << 3);
294 numSymbols = howmany(numBits, bitsPerSymbol);
295 txTime = TURBO_SIFS_TIME
296 + TURBO_PREAMBLE_TIME
297 + (numSymbols * TURBO_SYMBOL_TIME);
300 HALDEBUG(ah, HAL_DEBUG_PHYIO,
301 "%s: unknown phy %u (rate ix %u)\n",
302 __func__, rates->info[rateix].phy, rateix);
310 WIRELESS_MODE_11a = 0,
311 WIRELESS_MODE_TURBO = 1,
312 WIRELESS_MODE_11b = 2,
313 WIRELESS_MODE_11g = 3,
314 WIRELESS_MODE_108g = 4,
320 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
322 if (IEEE80211_IS_CHAN_B(chan))
323 return WIRELESS_MODE_11b;
324 if (IEEE80211_IS_CHAN_G(chan))
325 return WIRELESS_MODE_11g;
326 if (IEEE80211_IS_CHAN_108G(chan))
327 return WIRELESS_MODE_108g;
328 if (IEEE80211_IS_CHAN_TURBO(chan))
329 return WIRELESS_MODE_TURBO;
330 return WIRELESS_MODE_11a;
334 * Convert between microseconds and core system clocks.
336 /* 11a Turbo 11b 11g 108g */
337 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
340 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
342 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
345 /* NB: ah_curchan may be null when called attach time */
347 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
348 if (IEEE80211_IS_CHAN_HT40(c))
351 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
356 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
358 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
361 /* NB: ah_curchan may be null when called attach time */
363 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
364 if (IEEE80211_IS_CHAN_HT40(c))
367 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
372 * Setup a h/w rate table's reverse lookup table and
373 * fill in ack durations. This routine is called for
374 * each rate table returned through the ah_getRateTable
375 * method. The reverse lookup tables are assumed to be
376 * initialized to zero (or at least the first entry).
377 * We use this as a key that indicates whether or not
378 * we've previously setup the reverse lookup table.
380 * XXX not reentrant, but shouldn't matter
383 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
385 #define N(a) (sizeof(a)/sizeof(a[0]))
388 if (rt->rateCodeToIndex[0] != 0) /* already setup */
390 for (i = 0; i < N(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 < N(rt->rateCodeToIndex));
397 rt->rateCodeToIndex[code] = i;
398 HALASSERT((code | rt->info[i].shortPreamble) <
399 N(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);
416 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
417 uint32_t capability, uint32_t *result)
419 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
422 case HAL_CAP_REG_DMN: /* regulatory domain */
423 *result = AH_PRIVATE(ah)->ah_currentRD;
425 case HAL_CAP_CIPHER: /* cipher handled in hardware */
426 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
428 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
430 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
431 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
432 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
434 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
436 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
437 *result = pCap->halKeyCacheSize;
439 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
440 *result = pCap->halTotalQueues;
442 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
443 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
444 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
445 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
446 case HAL_CAP_COMPRESSION:
447 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
449 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
450 case HAL_CAP_FASTFRAME:
451 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
452 case HAL_CAP_DIAG: /* hardware diagnostic support */
453 *result = AH_PRIVATE(ah)->ah_diagreg;
455 case HAL_CAP_TXPOW: /* global tx power limit */
456 switch (capability) {
457 case 0: /* facility is supported */
459 case 1: /* current limit */
460 *result = AH_PRIVATE(ah)->ah_powerLimit;
462 case 2: /* current max tx power */
463 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
465 case 3: /* scale factor */
466 *result = AH_PRIVATE(ah)->ah_tpScale;
470 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
471 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
472 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
473 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
474 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
476 case HAL_CAP_RFSILENT: /* rfsilent support */
477 switch (capability) {
478 case 0: /* facility is supported */
479 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
480 case 1: /* current setting */
481 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
482 HAL_OK : HAL_ENOTSUPP;
483 case 2: /* rfsilent config */
484 *result = AH_PRIVATE(ah)->ah_rfsilent;
490 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
491 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
493 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
494 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
495 *result = pCap->halTxChainMask;
497 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
498 *result = pCap->halRxChainMask;
500 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
501 *result = pCap->halTstampPrecision;
503 case HAL_CAP_INTRMASK: /* mask of supported interrupts */
504 *result = pCap->halIntrMask;
506 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */
507 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
514 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
515 uint32_t capability, uint32_t setting, HAL_STATUS *status)
520 switch (capability) {
522 if (setting <= HAL_TP_SCALE_MIN) {
523 AH_PRIVATE(ah)->ah_tpScale = setting;
529 case HAL_CAP_RFSILENT: /* rfsilent support */
531 * NB: allow even if halRfSilentSupport is false
532 * in case the EEPROM is misprogrammed.
534 switch (capability) {
535 case 1: /* current setting */
536 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
538 case 2: /* rfsilent config */
539 /* XXX better done per-chip for validation? */
540 AH_PRIVATE(ah)->ah_rfsilent = setting;
544 case HAL_CAP_REG_DMN: /* regulatory domain */
545 AH_PRIVATE(ah)->ah_currentRD = setting;
547 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
548 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
554 *status = HAL_EINVAL;
559 * Common support for getDiagState method.
563 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
564 void *dstbuf, int space)
566 uint32_t *dp = dstbuf;
569 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
570 u_int r = regs[i].start;
571 u_int e = regs[i].end;
573 space -= sizeof(uint32_t);
575 *dp++ = OS_REG_READ(ah, r);
576 r += sizeof(uint32_t);
577 space -= sizeof(uint32_t);
578 } while (r <= e && space >= sizeof(uint32_t));
580 return (char *) dp - (char *) dstbuf;
584 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
586 while (space >= sizeof(HAL_REGWRITE)) {
587 OS_REG_WRITE(ah, regs->addr, regs->value);
588 regs++, space -= sizeof(HAL_REGWRITE);
593 ath_hal_getdiagstate(struct ath_hal *ah, int request,
594 const void *args, uint32_t argsize,
595 void **result, uint32_t *resultsize)
599 *result = &AH_PRIVATE(ah)->ah_devid;
600 *resultsize = sizeof(HAL_REVS);
603 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
605 case HAL_DIAG_SETREGS:
606 ath_hal_setregs(ah, args, argsize);
609 case HAL_DIAG_FATALERR:
610 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
611 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
613 case HAL_DIAG_EEREAD:
614 if (argsize != sizeof(uint16_t))
616 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
618 *resultsize = sizeof(uint16_t);
620 #ifdef AH_PRIVATE_DIAG
621 case HAL_DIAG_SETKEY: {
622 const HAL_DIAG_KEYVAL *dk;
624 if (argsize != sizeof(HAL_DIAG_KEYVAL))
626 dk = (const HAL_DIAG_KEYVAL *)args;
627 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
628 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
630 case HAL_DIAG_RESETKEY:
631 if (argsize != sizeof(uint16_t))
633 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
634 #ifdef AH_SUPPORT_WRITE_EEPROM
635 case HAL_DIAG_EEWRITE: {
636 const HAL_DIAG_EEVAL *ee;
637 if (argsize != sizeof(HAL_DIAG_EEVAL))
639 ee = (const HAL_DIAG_EEVAL *)args;
640 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
642 #endif /* AH_SUPPORT_WRITE_EEPROM */
643 #endif /* AH_PRIVATE_DIAG */
644 case HAL_DIAG_11NCOMPAT:
646 *resultsize = sizeof(uint32_t);
647 *((uint32_t *)(*result)) =
648 AH_PRIVATE(ah)->ah_11nCompat;
649 } else if (argsize == sizeof(uint32_t)) {
650 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
659 * Set the properties of the tx queue with the parameters
663 ath_hal_setTxQProps(struct ath_hal *ah,
664 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
668 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
669 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
670 "%s: inactive queue\n", __func__);
673 /* XXX validate parameters */
674 qi->tqi_ver = qInfo->tqi_ver;
675 qi->tqi_subtype = qInfo->tqi_subtype;
676 qi->tqi_qflags = qInfo->tqi_qflags;
677 qi->tqi_priority = qInfo->tqi_priority;
678 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
679 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
681 qi->tqi_aifs = INIT_AIFS;
682 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
683 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
684 /* make sure that the CWmin is of the form (2^n - 1) */
686 while (qi->tqi_cwmin < cw)
687 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
689 qi->tqi_cwmin = qInfo->tqi_cwmin;
690 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
691 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
692 /* make sure that the CWmax is of the form (2^n - 1) */
694 while (qi->tqi_cwmax < cw)
695 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
697 qi->tqi_cwmax = INIT_CWMAX;
698 /* Set retry limit values */
699 if (qInfo->tqi_shretry != 0)
700 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
702 qi->tqi_shretry = INIT_SH_RETRY;
703 if (qInfo->tqi_lgretry != 0)
704 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
706 qi->tqi_lgretry = INIT_LG_RETRY;
707 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
708 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
709 qi->tqi_burstTime = qInfo->tqi_burstTime;
710 qi->tqi_readyTime = qInfo->tqi_readyTime;
712 switch (qInfo->tqi_subtype) {
714 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
715 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
718 break; /* NB: silence compiler */
724 ath_hal_getTxQProps(struct ath_hal *ah,
725 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
727 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
728 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
729 "%s: inactive queue\n", __func__);
733 qInfo->tqi_qflags = qi->tqi_qflags;
734 qInfo->tqi_ver = qi->tqi_ver;
735 qInfo->tqi_subtype = qi->tqi_subtype;
736 qInfo->tqi_qflags = qi->tqi_qflags;
737 qInfo->tqi_priority = qi->tqi_priority;
738 qInfo->tqi_aifs = qi->tqi_aifs;
739 qInfo->tqi_cwmin = qi->tqi_cwmin;
740 qInfo->tqi_cwmax = qi->tqi_cwmax;
741 qInfo->tqi_shretry = qi->tqi_shretry;
742 qInfo->tqi_lgretry = qi->tqi_lgretry;
743 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
744 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
745 qInfo->tqi_burstTime = qi->tqi_burstTime;
746 qInfo->tqi_readyTime = qi->tqi_readyTime;
750 /* 11a Turbo 11b 11g 108g */
751 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
754 * Read the current channel noise floor and return.
755 * If nf cal hasn't finished, channel noise floor should be 0
756 * and we return a nominal value based on band and frequency.
758 * NB: This is a private routine used by per-chip code to
759 * implement the ah_getChanNoise method.
762 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
764 HAL_CHANNEL_INTERNAL *ichan;
766 ichan = ath_hal_checkchannel(ah, chan);
767 if (ichan == AH_NULL) {
768 HALDEBUG(ah, HAL_DEBUG_NFCAL,
769 "%s: invalid channel %u/0x%x; no mapping\n",
770 __func__, chan->ic_freq, chan->ic_flags);
773 if (ichan->rawNoiseFloor == 0) {
774 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
776 HALASSERT(mode < WIRELESS_MODE_MAX);
777 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
779 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
783 * Process all valid raw noise floors into the dBm noise floor values.
784 * Though our device has no reference for a dBm noise floor, we perform
785 * a relative minimization of NF's based on the lowest NF found across a
789 ath_hal_process_noisefloor(struct ath_hal *ah)
791 HAL_CHANNEL_INTERNAL *c;
792 int16_t correct2, correct5;
793 int16_t lowest2, lowest5;
797 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
798 * for statistically recorded NF/channel deviation.
800 correct2 = lowest2 = 0;
801 correct5 = lowest5 = 0;
802 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
806 c = &AH_PRIVATE(ah)->ah_channels[i];
807 if (c->rawNoiseFloor >= 0)
809 /* XXX can't identify proper mode */
810 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
811 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
812 ath_hal_getNfAdjust(ah, c);
813 if (IS_CHAN_5GHZ(c)) {
816 correct5 = NOISE_FLOOR[mode] -
817 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
822 correct2 = NOISE_FLOOR[mode] -
823 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
828 /* Correct the channels to reach the expected NF value */
829 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
830 c = &AH_PRIVATE(ah)->ah_channels[i];
831 if (c->rawNoiseFloor >= 0)
833 /* Apply correction factor */
834 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
835 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
836 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
837 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
842 * INI support routines.
846 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
851 HALASSERT(col < ia->cols);
852 for (r = 0; r < ia->rows; r++) {
853 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
854 HAL_INI_VAL(ia, r, col));
861 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
865 HALASSERT(col < ia->cols);
866 for (r = 0; r < ia->rows; r++)
867 data[r] = HAL_INI_VAL(ia, r, col);
871 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
872 const uint32_t data[], int regWr)
876 for (r = 0; r < ia->rows; r++) {
877 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);