2 * Copyright (c) 2002-2008 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: src/sys/dev/ath/ath_hal/ah.c,v 1.2.2.1.2.1 2009/04/15 03:14:26 kensmith Exp $
22 #include "ah_internal.h"
24 /* linker set of registered chips */
25 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
28 * Check the set of registered chips to see if any recognize
29 * the device as one they can support.
32 ath_hal_probe(uint16_t vendorid, uint16_t devid)
34 struct ath_hal_chip * const *pchip;
36 OS_SET_FOREACH(pchip, ah_chips) {
37 const char *name = (*pchip)->probe(vendorid, devid);
45 * Attach detects device chip revisions, initializes the hwLayer
46 * function list, reads EEPROM information,
47 * selects reset vectors, and performs a short self test.
48 * Any failures will return an error that should cause a hardware
52 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
53 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
55 struct ath_hal_chip * const *pchip;
57 OS_SET_FOREACH(pchip, ah_chips) {
58 struct ath_hal_chip *chip = *pchip;
61 /* XXX don't have vendorid, assume atheros one works */
62 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
64 ah = chip->attach(devid, sc, st, sh, error);
66 /* copy back private state to public area */
67 ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
68 ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
69 ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
70 ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
71 ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
72 ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
73 ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
80 /* linker set of registered RF backends */
81 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
84 * Check the set of registered RF backends to see if
85 * any recognize the device as one they can support.
88 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
90 struct ath_hal_rf * const *prf;
92 OS_SET_FOREACH(prf, ah_rfs) {
93 struct ath_hal_rf *rf = *prf;
97 *ecode = HAL_ENOTSUPP;
102 * Poll the register looking for a specific value.
105 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
107 #define AH_TIMEOUT 1000
110 for (i = 0; i < AH_TIMEOUT; i++) {
111 if ((OS_REG_READ(ah, reg) & mask) == val)
115 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
116 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
117 __func__, reg, OS_REG_READ(ah, reg), mask, val);
123 * Reverse the bits starting at the low bit for a value of
127 ath_hal_reverseBits(uint32_t val, uint32_t n)
132 for (i = 0, retval = 0; i < n; i++) {
133 retval = (retval << 1) | (val & 1);
140 * Compute the time to transmit a frame of length frameLen bytes
141 * using the specified rate, phy, and short preamble setting.
144 ath_hal_computetxtime(struct ath_hal *ah,
145 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
146 HAL_BOOL shortPreamble)
148 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
151 kbps = rates->info[rateix].rateKbps;
153 * index can be invalid duting dynamic Turbo transitions.
155 if(kbps == 0) return 0;
156 switch (rates->info[rateix].phy) {
158 case IEEE80211_T_CCK:
159 #define CCK_SIFS_TIME 10
160 #define CCK_PREAMBLE_BITS 144
161 #define CCK_PLCP_BITS 48
162 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
163 if (shortPreamble && rates->info[rateix].shortPreamble)
165 numBits = frameLen << 3;
166 txTime = CCK_SIFS_TIME + phyTime
167 + ((numBits * 1000)/kbps);
170 #undef CCK_PREAMBLE_BITS
173 case IEEE80211_T_OFDM:
174 #define OFDM_SIFS_TIME 16
175 #define OFDM_PREAMBLE_TIME 20
176 #define OFDM_PLCP_BITS 22
177 #define OFDM_SYMBOL_TIME 4
179 #define OFDM_SIFS_TIME_HALF 32
180 #define OFDM_PREAMBLE_TIME_HALF 40
181 #define OFDM_PLCP_BITS_HALF 22
182 #define OFDM_SYMBOL_TIME_HALF 8
184 #define OFDM_SIFS_TIME_QUARTER 64
185 #define OFDM_PREAMBLE_TIME_QUARTER 80
186 #define OFDM_PLCP_BITS_QUARTER 22
187 #define OFDM_SYMBOL_TIME_QUARTER 16
189 if (AH_PRIVATE(ah)->ah_curchan &&
190 IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
191 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
192 HALASSERT(bitsPerSymbol != 0);
194 numBits = OFDM_PLCP_BITS + (frameLen << 3);
195 numSymbols = howmany(numBits, bitsPerSymbol);
196 txTime = OFDM_SIFS_TIME_QUARTER
197 + OFDM_PREAMBLE_TIME_QUARTER
198 + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
199 } else if (AH_PRIVATE(ah)->ah_curchan &&
200 IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
201 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
202 HALASSERT(bitsPerSymbol != 0);
204 numBits = OFDM_PLCP_BITS + (frameLen << 3);
205 numSymbols = howmany(numBits, bitsPerSymbol);
206 txTime = OFDM_SIFS_TIME_HALF +
207 OFDM_PREAMBLE_TIME_HALF
208 + (numSymbols * OFDM_SYMBOL_TIME_HALF);
209 } else { /* full rate channel */
210 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
211 HALASSERT(bitsPerSymbol != 0);
213 numBits = OFDM_PLCP_BITS + (frameLen << 3);
214 numSymbols = howmany(numBits, bitsPerSymbol);
215 txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
216 + (numSymbols * OFDM_SYMBOL_TIME);
220 #undef OFDM_SIFS_TIME
221 #undef OFDM_PREAMBLE_TIME
222 #undef OFDM_PLCP_BITS
223 #undef OFDM_SYMBOL_TIME
225 case IEEE80211_T_TURBO:
226 #define TURBO_SIFS_TIME 8
227 #define TURBO_PREAMBLE_TIME 14
228 #define TURBO_PLCP_BITS 22
229 #define TURBO_SYMBOL_TIME 4
230 /* we still save OFDM rates in kbps - so double them */
231 bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
232 HALASSERT(bitsPerSymbol != 0);
234 numBits = TURBO_PLCP_BITS + (frameLen << 3);
235 numSymbols = howmany(numBits, bitsPerSymbol);
236 txTime = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME
237 + (numSymbols * TURBO_SYMBOL_TIME);
239 #undef TURBO_SIFS_TIME
240 #undef TURBO_PREAMBLE_TIME
241 #undef TURBO_PLCP_BITS
242 #undef TURBO_SYMBOL_TIME
245 HALDEBUG(ah, HAL_DEBUG_PHYIO,
246 "%s: unknown phy %u (rate ix %u)\n",
247 __func__, rates->info[rateix].phy, rateix);
255 mapgsm(u_int freq, u_int flags)
258 if (flags & CHANNEL_QUARTER)
260 else if (flags & CHANNEL_HALF)
264 return (freq - 24220) / 5;
268 mappsb(u_int freq, u_int flags)
270 return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
274 * Convert GHz frequency to IEEE channel number.
277 ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags)
279 if (flags & CHANNEL_2GHZ) { /* 2GHz band */
283 if (ath_hal_isgsmsku(ah))
284 return mapgsm(freq, flags);
285 return ((int)freq - 2407) / 5;
287 return 15 + ((freq - 2512) / 20);
288 } else if (flags & CHANNEL_5GHZ) {/* 5Ghz band */
289 if (ath_hal_ispublicsafetysku(ah) &&
290 IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
291 return mappsb(freq, flags);
292 } else if ((flags & CHANNEL_A) && (freq <= 5000)) {
293 return (freq - 4000) / 5;
295 return (freq - 5000) / 5;
297 } else { /* either, guess */
301 if (ath_hal_isgsmsku(ah))
302 return mapgsm(freq, flags);
303 return ((int)freq - 2407) / 5;
306 if (ath_hal_ispublicsafetysku(ah) &&
307 IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
308 return mappsb(freq, flags);
309 } else if (freq > 4900) {
310 return (freq - 4000) / 5;
312 return 15 + ((freq - 2512) / 20);
315 return (freq - 5000) / 5;
320 WIRELESS_MODE_11a = 0,
321 WIRELESS_MODE_TURBO = 1,
322 WIRELESS_MODE_11b = 2,
323 WIRELESS_MODE_11g = 3,
324 WIRELESS_MODE_108g = 4,
330 ath_hal_chan2wmode(struct ath_hal *ah, const HAL_CHANNEL *chan)
332 if (IS_CHAN_CCK(chan))
333 return WIRELESS_MODE_11b;
335 return WIRELESS_MODE_11g;
336 if (IS_CHAN_108G(chan))
337 return WIRELESS_MODE_108g;
338 if (IS_CHAN_TURBO(chan))
339 return WIRELESS_MODE_TURBO;
340 return WIRELESS_MODE_11a;
344 * Convert between microseconds and core system clocks.
346 /* 11a Turbo 11b 11g 108g */
347 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 };
350 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
352 const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
355 /* NB: ah_curchan may be null when called attach time */
357 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
360 else if (IS_CHAN_HALF_RATE(c))
362 else if (IS_CHAN_QUARTER_RATE(c))
365 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
370 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
372 const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan;
375 /* NB: ah_curchan may be null when called attach time */
377 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
380 else if (IS_CHAN_HALF_RATE(c))
382 else if (IS_CHAN_QUARTER_RATE(c))
385 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b];
390 * Setup a h/w rate table's reverse lookup table and
391 * fill in ack durations. This routine is called for
392 * each rate table returned through the ah_getRateTable
393 * method. The reverse lookup tables are assumed to be
394 * initialized to zero (or at least the first entry).
395 * We use this as a key that indicates whether or not
396 * we've previously setup the reverse lookup table.
398 * XXX not reentrant, but shouldn't matter
401 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
403 #define N(a) (sizeof(a)/sizeof(a[0]))
406 if (rt->rateCodeToIndex[0] != 0) /* already setup */
408 for (i = 0; i < N(rt->rateCodeToIndex); i++)
409 rt->rateCodeToIndex[i] = (uint8_t) -1;
410 for (i = 0; i < rt->rateCount; i++) {
411 uint8_t code = rt->info[i].rateCode;
412 uint8_t cix = rt->info[i].controlRate;
414 HALASSERT(code < N(rt->rateCodeToIndex));
415 rt->rateCodeToIndex[code] = i;
416 HALASSERT((code | rt->info[i].shortPreamble) <
417 N(rt->rateCodeToIndex));
418 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
420 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
421 * depends on whether they are marked as basic rates;
422 * the static tables are setup with an 11b-compatible
423 * 2Mb/s rate which will work but is suboptimal
425 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
426 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
427 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
428 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
434 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
435 uint32_t capability, uint32_t *result)
437 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
440 case HAL_CAP_REG_DMN: /* regulatory domain */
441 *result = AH_PRIVATE(ah)->ah_currentRD;
443 case HAL_CAP_CIPHER: /* cipher handled in hardware */
444 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
446 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
448 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */
449 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
450 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */
452 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
454 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */
455 *result = pCap->halKeyCacheSize;
457 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */
458 *result = pCap->halTotalQueues;
460 case HAL_CAP_VEOL: /* hardware supports virtual EOL */
461 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
462 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */
463 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
464 case HAL_CAP_COMPRESSION:
465 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
467 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
468 case HAL_CAP_FASTFRAME:
469 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
470 case HAL_CAP_DIAG: /* hardware diagnostic support */
471 *result = AH_PRIVATE(ah)->ah_diagreg;
473 case HAL_CAP_TXPOW: /* global tx power limit */
474 switch (capability) {
475 case 0: /* facility is supported */
477 case 1: /* current limit */
478 *result = AH_PRIVATE(ah)->ah_powerLimit;
480 case 2: /* current max tx power */
481 *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
483 case 3: /* scale factor */
484 *result = AH_PRIVATE(ah)->ah_tpScale;
488 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */
489 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
490 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
491 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
492 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
494 case HAL_CAP_RFSILENT: /* rfsilent support */
495 switch (capability) {
496 case 0: /* facility is supported */
497 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
498 case 1: /* current setting */
499 return AH_PRIVATE(ah)->ah_rfkillEnabled ?
500 HAL_OK : HAL_ENOTSUPP;
501 case 2: /* rfsilent config */
502 *result = AH_PRIVATE(ah)->ah_rfsilent;
507 #ifdef AH_SUPPORT_11D
512 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
513 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
515 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
516 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */
517 *result = pCap->halTxChainMask;
519 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */
520 *result = pCap->halRxChainMask;
522 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
523 *result = pCap->halTstampPrecision;
531 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
532 uint32_t capability, uint32_t setting, HAL_STATUS *status)
537 switch (capability) {
539 if (setting <= HAL_TP_SCALE_MIN) {
540 AH_PRIVATE(ah)->ah_tpScale = setting;
546 case HAL_CAP_RFSILENT: /* rfsilent support */
548 * NB: allow even if halRfSilentSupport is false
549 * in case the EEPROM is misprogrammed.
551 switch (capability) {
552 case 1: /* current setting */
553 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
555 case 2: /* rfsilent config */
556 /* XXX better done per-chip for validation? */
557 AH_PRIVATE(ah)->ah_rfsilent = setting;
561 case HAL_CAP_REG_DMN: /* regulatory domain */
562 AH_PRIVATE(ah)->ah_currentRD = setting;
564 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
565 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
571 *status = HAL_EINVAL;
576 * Common support for getDiagState method.
580 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
581 void *dstbuf, int space)
583 uint32_t *dp = dstbuf;
586 for (i = 0; space >= 2*sizeof(uint32_t); i++) {
587 u_int r = regs[i].start;
588 u_int e = regs[i].end;
590 space -= sizeof(uint32_t);
592 *dp++ = OS_REG_READ(ah, r);
593 r += sizeof(uint32_t);
594 space -= sizeof(uint32_t);
595 } while (r <= e && space >= sizeof(uint32_t));
597 return (char *) dp - (char *) dstbuf;
601 ath_hal_getdiagstate(struct ath_hal *ah, int request,
602 const void *args, uint32_t argsize,
603 void **result, uint32_t *resultsize)
607 *result = &AH_PRIVATE(ah)->ah_devid;
608 *resultsize = sizeof(HAL_REVS);
611 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
613 case HAL_DIAG_FATALERR:
614 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
615 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
617 case HAL_DIAG_EEREAD:
618 if (argsize != sizeof(uint16_t))
620 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
622 *resultsize = sizeof(uint16_t);
624 #ifdef AH_PRIVATE_DIAG
625 case HAL_DIAG_SETKEY: {
626 const HAL_DIAG_KEYVAL *dk;
628 if (argsize != sizeof(HAL_DIAG_KEYVAL))
630 dk = (const HAL_DIAG_KEYVAL *)args;
631 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
632 &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
634 case HAL_DIAG_RESETKEY:
635 if (argsize != sizeof(uint16_t))
637 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
638 #ifdef AH_SUPPORT_WRITE_EEPROM
639 case HAL_DIAG_EEWRITE: {
640 const HAL_DIAG_EEVAL *ee;
641 if (argsize != sizeof(HAL_DIAG_EEVAL))
643 ee = (const HAL_DIAG_EEVAL *)args;
644 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
646 #endif /* AH_SUPPORT_WRITE_EEPROM */
647 #endif /* AH_PRIVATE_DIAG */
648 case HAL_DIAG_11NCOMPAT:
650 *resultsize = sizeof(uint32_t);
651 *((uint32_t *)(*result)) =
652 AH_PRIVATE(ah)->ah_11nCompat;
653 } else if (argsize == sizeof(uint32_t)) {
654 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
663 * Set the properties of the tx queue with the parameters
667 ath_hal_setTxQProps(struct ath_hal *ah,
668 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
672 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
673 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
674 "%s: inactive queue\n", __func__);
677 /* XXX validate parameters */
678 qi->tqi_ver = qInfo->tqi_ver;
679 qi->tqi_subtype = qInfo->tqi_subtype;
680 qi->tqi_qflags = qInfo->tqi_qflags;
681 qi->tqi_priority = qInfo->tqi_priority;
682 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
683 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
685 qi->tqi_aifs = INIT_AIFS;
686 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
687 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
688 /* make sure that the CWmin is of the form (2^n - 1) */
690 while (qi->tqi_cwmin < cw)
691 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
693 qi->tqi_cwmin = qInfo->tqi_cwmin;
694 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
695 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
696 /* make sure that the CWmax is of the form (2^n - 1) */
698 while (qi->tqi_cwmax < cw)
699 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
701 qi->tqi_cwmax = INIT_CWMAX;
702 /* Set retry limit values */
703 if (qInfo->tqi_shretry != 0)
704 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
706 qi->tqi_shretry = INIT_SH_RETRY;
707 if (qInfo->tqi_lgretry != 0)
708 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
710 qi->tqi_lgretry = INIT_LG_RETRY;
711 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
712 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
713 qi->tqi_burstTime = qInfo->tqi_burstTime;
714 qi->tqi_readyTime = qInfo->tqi_readyTime;
716 switch (qInfo->tqi_subtype) {
718 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
719 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
722 break; /* NB: silence compiler */
728 ath_hal_getTxQProps(struct ath_hal *ah,
729 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
731 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
732 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
733 "%s: inactive queue\n", __func__);
737 qInfo->tqi_qflags = qi->tqi_qflags;
738 qInfo->tqi_ver = qi->tqi_ver;
739 qInfo->tqi_subtype = qi->tqi_subtype;
740 qInfo->tqi_qflags = qi->tqi_qflags;
741 qInfo->tqi_priority = qi->tqi_priority;
742 qInfo->tqi_aifs = qi->tqi_aifs;
743 qInfo->tqi_cwmin = qi->tqi_cwmin;
744 qInfo->tqi_cwmax = qi->tqi_cwmax;
745 qInfo->tqi_shretry = qi->tqi_shretry;
746 qInfo->tqi_lgretry = qi->tqi_lgretry;
747 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
748 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
749 qInfo->tqi_burstTime = qi->tqi_burstTime;
750 qInfo->tqi_readyTime = qi->tqi_readyTime;
754 /* 11a Turbo 11b 11g 108g */
755 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 };
758 * Read the current channel noise floor and return.
759 * If nf cal hasn't finished, channel noise floor should be 0
760 * and we return a nominal value based on band and frequency.
762 * NB: This is a private routine used by per-chip code to
763 * implement the ah_getChanNoise method.
766 ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan)
768 HAL_CHANNEL_INTERNAL *ichan;
770 ichan = ath_hal_checkchannel(ah, chan);
771 if (ichan == AH_NULL) {
772 HALDEBUG(ah, HAL_DEBUG_NFCAL,
773 "%s: invalid channel %u/0x%x; no mapping\n",
774 __func__, chan->channel, chan->channelFlags);
777 if (ichan->rawNoiseFloor == 0) {
778 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
780 HALASSERT(mode < WIRELESS_MODE_MAX);
781 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
783 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
787 * Process all valid raw noise floors into the dBm noise floor values.
788 * Though our device has no reference for a dBm noise floor, we perform
789 * a relative minimization of NF's based on the lowest NF found across a
793 ath_hal_process_noisefloor(struct ath_hal *ah)
795 HAL_CHANNEL_INTERNAL *c;
796 int16_t correct2, correct5;
797 int16_t lowest2, lowest5;
801 * Find the lowest 2GHz and 5GHz noise floor values after adjusting
802 * for statistically recorded NF/channel deviation.
804 correct2 = lowest2 = 0;
805 correct5 = lowest5 = 0;
806 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
810 c = &AH_PRIVATE(ah)->ah_channels[i];
811 if (c->rawNoiseFloor >= 0)
813 mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) c);
814 HALASSERT(mode < WIRELESS_MODE_MAX);
815 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
816 ath_hal_getNfAdjust(ah, c);
817 if (IS_CHAN_5GHZ(c)) {
820 correct5 = NOISE_FLOOR[mode] -
821 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
826 correct2 = NOISE_FLOOR[mode] -
827 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
832 /* Correct the channels to reach the expected NF value */
833 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
834 c = &AH_PRIVATE(ah)->ah_channels[i];
835 if (c->rawNoiseFloor >= 0)
837 /* Apply correction factor */
838 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
839 (IS_CHAN_5GHZ(c) ? correct5 : correct2);
840 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u/0x%x raw nf %d adjust %d\n",
841 c->channel, c->channelFlags, c->rawNoiseFloor,
842 c->noiseFloorAdjust);
847 * INI support routines.
851 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
856 for (r = 0; r < ia->rows; r++) {
857 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
858 HAL_INI_VAL(ia, r, col));
865 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
869 for (r = 0; r < ia->rows; r++)
870 data[r] = HAL_INI_VAL(ia, r, col);
874 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
875 const uint32_t data[], int regWr)
879 for (r = 0; r < ia->rows; r++) {
880 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);