1/* 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 * 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. 8 * 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. 16 * 17 * $Id: ah.c,v 1.3 2011/03/07 11:25:42 cegger Exp $ 18 */ 19#include "opt_ah.h" 20 21#include "ah.h" 22#include "ah_internal.h" 23#include "ah_devid.h" 24 25/* linker set of registered chips */ 26OS_SET_DECLARE(ah_chips, struct ath_hal_chip); 27 28/* 29 * Check the set of registered chips to see if any recognize 30 * the device as one they can support. 31 */ 32const char* 33ath_hal_probe(uint16_t vendorid, uint16_t devid) 34{ 35 struct ath_hal_chip * const *pchip; 36 37 OS_SET_FOREACH(pchip, ah_chips) { 38 const char *name = (*pchip)->probe(vendorid, devid); 39 if (name != AH_NULL) 40 return name; 41 } 42 return AH_NULL; 43} 44 45/* 46 * Attach detects device chip revisions, initializes the hwLayer 47 * function list, reads EEPROM information, 48 * selects reset vectors, and performs a short self test. 49 * Any failures will return an error that should cause a hardware 50 * disable. 51 */ 52struct ath_hal* 53ath_hal_attach(uint16_t devid, HAL_SOFTC sc, 54 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error) 55{ 56 struct ath_hal_chip * const *pchip; 57 58 OS_SET_FOREACH(pchip, ah_chips) { 59 struct ath_hal_chip *chip = *pchip; 60 struct ath_hal *ah; 61 62 /* XXX don't have vendorid, assume atheros one works */ 63 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL) 64 continue; 65 ah = chip->attach(devid, sc, st, sh, error); 66 if (ah != AH_NULL) { 67 /* copy back private state to public area */ 68 ah->ah_devid = AH_PRIVATE(ah)->ah_devid; 69 ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid; 70 ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion; 71 ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev; 72 ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev; 73 ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev; 74 ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev; 75 return ah; 76 } 77 } 78 return AH_NULL; 79} 80 81/* linker set of registered RF backends */ 82OS_SET_DECLARE(ah_rfs, struct ath_hal_rf); 83 84/* 85 * Check the set of registered RF backends to see if 86 * any recognize the device as one they can support. 87 */ 88struct ath_hal_rf * 89ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode) 90{ 91#ifdef AH_HAS_RF 92 struct ath_hal_rf * const *prf; 93 94 OS_SET_FOREACH(prf, ah_rfs) { 95 struct ath_hal_rf *rf = *prf; 96 if (rf->probe(ah)) 97 return rf; 98 } 99 *ecode = HAL_ENOTSUPP; 100#endif 101 return AH_NULL; 102} 103 104/* 105 * Poll the register looking for a specific value. 106 */ 107HAL_BOOL 108ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val) 109{ 110#define AH_TIMEOUT 1000 111 int i; 112 113 for (i = 0; i < AH_TIMEOUT; i++) { 114 if ((OS_REG_READ(ah, reg) & mask) == val) 115 return AH_TRUE; 116 OS_DELAY(10); 117 } 118 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO, 119 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", 120 __func__, reg, OS_REG_READ(ah, reg), mask, val); 121 return AH_FALSE; 122#undef AH_TIMEOUT 123} 124 125/* 126 * Reverse the bits starting at the low bit for a value of 127 * bit_count in size 128 */ 129uint32_t 130ath_hal_reverseBits(uint32_t val, uint32_t n) 131{ 132 uint32_t retval; 133 int i; 134 135 for (i = 0, retval = 0; i < n; i++) { 136 retval = (retval << 1) | (val & 1); 137 val >>= 1; 138 } 139 return retval; 140} 141 142/* 143 * Compute the time to transmit a frame of length frameLen bytes 144 * using the specified rate, phy, and short preamble setting. 145 */ 146uint16_t 147ath_hal_computetxtime(struct ath_hal *ah, 148 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix, 149 HAL_BOOL shortPreamble) 150{ 151 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime; 152 uint32_t kbps; 153 154 kbps = rates->info[rateix].rateKbps; 155 /* 156 * index can be invalid duting dynamic Turbo transitions. 157 */ 158 if(kbps == 0) return 0; 159 switch (rates->info[rateix].phy) { 160 161 case IEEE80211_T_CCK: 162#define CCK_SIFS_TIME 10 163#define CCK_PREAMBLE_BITS 144 164#define CCK_PLCP_BITS 48 165 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; 166 if (shortPreamble && rates->info[rateix].shortPreamble) 167 phyTime >>= 1; 168 numBits = frameLen << 3; 169 txTime = CCK_SIFS_TIME + phyTime 170 + ((numBits * 1000)/kbps); 171 break; 172#undef CCK_SIFS_TIME 173#undef CCK_PREAMBLE_BITS 174#undef CCK_PLCP_BITS 175 176 case IEEE80211_T_OFDM: 177#define OFDM_SIFS_TIME 16 178#define OFDM_PREAMBLE_TIME 20 179#define OFDM_PLCP_BITS 22 180#define OFDM_SYMBOL_TIME 4 181 182#define OFDM_SIFS_TIME_HALF 32 183#define OFDM_PREAMBLE_TIME_HALF 40 184#define OFDM_PLCP_BITS_HALF 22 185#define OFDM_SYMBOL_TIME_HALF 8 186 187#define OFDM_SIFS_TIME_QUARTER 64 188#define OFDM_PREAMBLE_TIME_QUARTER 80 189#define OFDM_PLCP_BITS_QUARTER 22 190#define OFDM_SYMBOL_TIME_QUARTER 16 191 192 if (AH_PRIVATE(ah)->ah_curchan && 193 IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { 194 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; 195 HALASSERT(bitsPerSymbol != 0); 196 197 numBits = OFDM_PLCP_BITS + (frameLen << 3); 198 numSymbols = howmany(numBits, bitsPerSymbol); 199 txTime = OFDM_SIFS_TIME_QUARTER 200 + OFDM_PREAMBLE_TIME_QUARTER 201 + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); 202 } else if (AH_PRIVATE(ah)->ah_curchan && 203 IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { 204 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000; 205 HALASSERT(bitsPerSymbol != 0); 206 207 numBits = OFDM_PLCP_BITS + (frameLen << 3); 208 numSymbols = howmany(numBits, bitsPerSymbol); 209 txTime = OFDM_SIFS_TIME_HALF + 210 OFDM_PREAMBLE_TIME_HALF 211 + (numSymbols * OFDM_SYMBOL_TIME_HALF); 212 } else { /* full rate channel */ 213 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; 214 HALASSERT(bitsPerSymbol != 0); 215 216 numBits = OFDM_PLCP_BITS + (frameLen << 3); 217 numSymbols = howmany(numBits, bitsPerSymbol); 218 txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME 219 + (numSymbols * OFDM_SYMBOL_TIME); 220 } 221 break; 222 223#undef OFDM_SIFS_TIME 224#undef OFDM_PREAMBLE_TIME 225#undef OFDM_PLCP_BITS 226#undef OFDM_SYMBOL_TIME 227 228 case IEEE80211_T_TURBO: 229#define TURBO_SIFS_TIME 8 230#define TURBO_PREAMBLE_TIME 14 231#define TURBO_PLCP_BITS 22 232#define TURBO_SYMBOL_TIME 4 233 /* we still save OFDM rates in kbps - so double them */ 234 bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000; 235 HALASSERT(bitsPerSymbol != 0); 236 237 numBits = TURBO_PLCP_BITS + (frameLen << 3); 238 numSymbols = howmany(numBits, bitsPerSymbol); 239 txTime = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME 240 + (numSymbols * TURBO_SYMBOL_TIME); 241 break; 242#undef TURBO_SIFS_TIME 243#undef TURBO_PREAMBLE_TIME 244#undef TURBO_PLCP_BITS 245#undef TURBO_SYMBOL_TIME 246 247 default: 248 HALDEBUG(ah, HAL_DEBUG_PHYIO, 249 "%s: unknown phy %u (rate ix %u)\n", 250 __func__, rates->info[rateix].phy, rateix); 251 txTime = 0; 252 break; 253 } 254 return txTime; 255} 256 257static __inline int 258mapgsm(u_int freq, u_int flags) 259{ 260 freq *= 10; 261 if (flags & CHANNEL_QUARTER) 262 freq += 5; 263 else if (flags & CHANNEL_HALF) 264 freq += 10; 265 else 266 freq += 20; 267 return (freq - 24220) / 5; 268} 269 270static __inline int 271mappsb(u_int freq, u_int flags) 272{ 273 return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5; 274} 275 276/* 277 * Convert GHz frequency to IEEE channel number. 278 */ 279int 280ath_hal_mhz2ieee(struct ath_hal *ah, u_int freq, u_int flags) 281{ 282 if (flags & CHANNEL_2GHZ) { /* 2GHz band */ 283 if (freq == 2484) 284 return 14; 285 if (freq < 2484) { 286 if (ath_hal_isgsmsku(ah)) 287 return mapgsm(freq, flags); 288 return ((int)freq - 2407) / 5; 289 } else 290 return 15 + ((freq - 2512) / 20); 291 } else if (flags & CHANNEL_5GHZ) {/* 5Ghz band */ 292 if (ath_hal_ispublicsafetysku(ah) && 293 IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { 294 return mappsb(freq, flags); 295 } else if ((flags & CHANNEL_A) && (freq <= 5000)) { 296 return (freq - 4000) / 5; 297 } else { 298 return (freq - 5000) / 5; 299 } 300 } else { /* either, guess */ 301 if (freq == 2484) 302 return 14; 303 if (freq < 2484) { 304 if (ath_hal_isgsmsku(ah)) 305 return mapgsm(freq, flags); 306 return ((int)freq - 2407) / 5; 307 } 308 if (freq < 5000) { 309 if (ath_hal_ispublicsafetysku(ah) && 310 IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { 311 return mappsb(freq, flags); 312 } else if (freq > 4900) { 313 return (freq - 4000) / 5; 314 } else { 315 return 15 + ((freq - 2512) / 20); 316 } 317 } 318 return (freq - 5000) / 5; 319 } 320} 321 322typedef enum { 323 WIRELESS_MODE_11a = 0, 324 WIRELESS_MODE_TURBO = 1, 325 WIRELESS_MODE_11b = 2, 326 WIRELESS_MODE_11g = 3, 327 WIRELESS_MODE_108g = 4, 328 329 WIRELESS_MODE_MAX 330} WIRELESS_MODE; 331 332static WIRELESS_MODE 333ath_hal_chan2wmode(struct ath_hal *ah, const HAL_CHANNEL *chan) 334{ 335 if (IS_CHAN_CCK(chan)) 336 return WIRELESS_MODE_11b; 337 if (IS_CHAN_G(chan)) 338 return WIRELESS_MODE_11g; 339 if (IS_CHAN_108G(chan)) 340 return WIRELESS_MODE_108g; 341 if (IS_CHAN_TURBO(chan)) 342 return WIRELESS_MODE_TURBO; 343 return WIRELESS_MODE_11a; 344} 345 346/* 347 * Convert between microseconds and core system clocks. 348 */ 349 /* 11a Turbo 11b 11g 108g */ 350static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 }; 351 352u_int 353ath_hal_mac_clks(struct ath_hal *ah, u_int usecs) 354{ 355 const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan; 356 u_int clks; 357 358 /* NB: ah_curchan may be null when called attach time */ 359 if (c != AH_NULL) { 360 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; 361 if (IS_CHAN_HT40(c)) 362 clks <<= 1; 363 else if (IS_CHAN_HALF_RATE(c)) 364 clks >>= 1; 365 else if (IS_CHAN_QUARTER_RATE(c)) 366 clks >>= 2; 367 } else 368 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b]; 369 return clks; 370} 371 372u_int 373ath_hal_mac_usec(struct ath_hal *ah, u_int clks) 374{ 375 const HAL_CHANNEL *c = (const HAL_CHANNEL *) AH_PRIVATE(ah)->ah_curchan; 376 u_int usec; 377 378 /* NB: ah_curchan may be null when called attach time */ 379 if (c != AH_NULL) { 380 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; 381 if (IS_CHAN_HT40(c)) 382 usec >>= 1; 383 else if (IS_CHAN_HALF_RATE(c)) 384 usec <<= 1; 385 else if (IS_CHAN_QUARTER_RATE(c)) 386 usec <<= 2; 387 } else 388 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b]; 389 return usec; 390} 391 392/* 393 * Setup a h/w rate table's reverse lookup table and 394 * fill in ack durations. This routine is called for 395 * each rate table returned through the ah_getRateTable 396 * method. The reverse lookup tables are assumed to be 397 * initialized to zero (or at least the first entry). 398 * We use this as a key that indicates whether or not 399 * we've previously setup the reverse lookup table. 400 * 401 * XXX not reentrant, but shouldn't matter 402 */ 403void 404ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt) 405{ 406#define N(a) (sizeof(a)/sizeof(a[0])) 407 int i; 408 409 if (rt->rateCodeToIndex[0] != 0) /* already setup */ 410 return; 411 for (i = 0; i < N(rt->rateCodeToIndex); i++) 412 rt->rateCodeToIndex[i] = (uint8_t) -1; 413 for (i = 0; i < rt->rateCount; i++) { 414 uint8_t code = rt->info[i].rateCode; 415 uint8_t cix = rt->info[i].controlRate; 416 417 HALASSERT(code < N(rt->rateCodeToIndex)); 418 rt->rateCodeToIndex[code] = i; 419 HALASSERT((code | rt->info[i].shortPreamble) < 420 N(rt->rateCodeToIndex)); 421 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i; 422 /* 423 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s 424 * depends on whether they are marked as basic rates; 425 * the static tables are setup with an 11b-compatible 426 * 2Mb/s rate which will work but is suboptimal 427 */ 428 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt, 429 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE); 430 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt, 431 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE); 432 } 433#undef N 434} 435 436HAL_STATUS 437ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 438 uint32_t capability, uint32_t *result) 439{ 440 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 441 442 switch (type) { 443 case HAL_CAP_REG_DMN: /* regulatory domain */ 444 *result = AH_PRIVATE(ah)->ah_currentRD; 445 return HAL_OK; 446 case HAL_CAP_CIPHER: /* cipher handled in hardware */ 447 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ 448 return HAL_ENOTSUPP; 449 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ 450 return HAL_ENOTSUPP; 451 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */ 452 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO; 453 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */ 454 return HAL_ENOTSUPP; 455 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ 456 return HAL_ENOTSUPP; 457 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */ 458 *result = pCap->halKeyCacheSize; 459 return HAL_OK; 460 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */ 461 *result = pCap->halTotalQueues; 462 return HAL_OK; 463 case HAL_CAP_VEOL: /* hardware supports virtual EOL */ 464 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP; 465 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */ 466 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK; 467 case HAL_CAP_COMPRESSION: 468 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP; 469 case HAL_CAP_BURST: 470 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP; 471 case HAL_CAP_FASTFRAME: 472 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP; 473 case HAL_CAP_DIAG: /* hardware diagnostic support */ 474 *result = AH_PRIVATE(ah)->ah_diagreg; 475 return HAL_OK; 476 case HAL_CAP_TXPOW: /* global tx power limit */ 477 switch (capability) { 478 case 0: /* facility is supported */ 479 return HAL_OK; 480 case 1: /* current limit */ 481 *result = AH_PRIVATE(ah)->ah_powerLimit; 482 return HAL_OK; 483 case 2: /* current max tx power */ 484 *result = AH_PRIVATE(ah)->ah_maxPowerLevel; 485 return HAL_OK; 486 case 3: /* scale factor */ 487 *result = AH_PRIVATE(ah)->ah_tpScale; 488 return HAL_OK; 489 } 490 return HAL_ENOTSUPP; 491 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */ 492 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP; 493 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ 494 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP; 495 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ 496 return HAL_ENOTSUPP; 497 case HAL_CAP_RFSILENT: /* rfsilent support */ 498 switch (capability) { 499 case 0: /* facility is supported */ 500 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP; 501 case 1: /* current setting */ 502 return AH_PRIVATE(ah)->ah_rfkillEnabled ? 503 HAL_OK : HAL_ENOTSUPP; 504 case 2: /* rfsilent config */ 505 *result = AH_PRIVATE(ah)->ah_rfsilent; 506 return HAL_OK; 507 } 508 return HAL_ENOTSUPP; 509 case HAL_CAP_11D: 510#ifdef AH_SUPPORT_11D 511 return HAL_OK; 512#else 513 return HAL_ENOTSUPP; 514#endif 515 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ 516 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP; 517 case HAL_CAP_HT: 518 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP; 519 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */ 520 *result = pCap->halTxChainMask; 521 return HAL_OK; 522 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */ 523 *result = pCap->halRxChainMask; 524 return HAL_OK; 525 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */ 526 *result = pCap->halTstampPrecision; 527 return HAL_OK; 528 case HAL_CAP_INTRMASK: /* mask of supported interrupts */ 529 *result = pCap->halIntrMask; 530 return HAL_OK; 531 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */ 532 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP; 533 default: 534 return HAL_EINVAL; 535 } 536} 537 538HAL_BOOL 539ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 540 uint32_t capability, uint32_t setting, HAL_STATUS *status) 541{ 542 543 switch (type) { 544 case HAL_CAP_TXPOW: 545 switch (capability) { 546 case 3: 547 if (setting <= HAL_TP_SCALE_MIN) { 548 AH_PRIVATE(ah)->ah_tpScale = setting; 549 return AH_TRUE; 550 } 551 break; 552 } 553 break; 554 case HAL_CAP_RFSILENT: /* rfsilent support */ 555 /* 556 * NB: allow even if halRfSilentSupport is false 557 * in case the EEPROM is misprogrammed. 558 */ 559 switch (capability) { 560 case 1: /* current setting */ 561 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0); 562 return AH_TRUE; 563 case 2: /* rfsilent config */ 564 /* XXX better done per-chip for validation? */ 565 AH_PRIVATE(ah)->ah_rfsilent = setting; 566 return AH_TRUE; 567 } 568 break; 569 case HAL_CAP_REG_DMN: /* regulatory domain */ 570 AH_PRIVATE(ah)->ah_currentRD = setting; 571 return AH_TRUE; 572 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ 573 AH_PRIVATE(ah)->ah_rxornIsFatal = setting; 574 return AH_TRUE; 575 default: 576 break; 577 } 578 if (status) 579 *status = HAL_EINVAL; 580 return AH_FALSE; 581} 582 583/* 584 * Common support for getDiagState method. 585 */ 586 587static u_int 588ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs, 589 void *dstbuf, int space) 590{ 591 uint32_t *dp = dstbuf; 592 int i; 593 594 for (i = 0; space >= 2*sizeof(uint32_t); i++) { 595 u_int r = regs[i].start; 596 u_int e = regs[i].end; 597 *dp++ = (r<<16) | e; 598 space -= sizeof(uint32_t); 599 do { 600 *dp++ = OS_REG_READ(ah, r); 601 r += sizeof(uint32_t); 602 space -= sizeof(uint32_t); 603 } while (r <= e && space >= sizeof(uint32_t)); 604 } 605 return (char *) dp - (char *) dstbuf; 606} 607 608HAL_BOOL 609ath_hal_getdiagstate(struct ath_hal *ah, int request, 610 const void *args, uint32_t argsize, 611 void **result, uint32_t *resultsize) 612{ 613 switch (request) { 614 case HAL_DIAG_REVS: 615 *result = &AH_PRIVATE(ah)->ah_devid; 616 *resultsize = sizeof(HAL_REVS); 617 return AH_TRUE; 618 case HAL_DIAG_REGS: 619 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize); 620 return AH_TRUE; 621 case HAL_DIAG_FATALERR: 622 *result = &AH_PRIVATE(ah)->ah_fatalState[0]; 623 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState); 624 return AH_TRUE; 625 case HAL_DIAG_EEREAD: 626 if (argsize != sizeof(uint16_t)) 627 return AH_FALSE; 628 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result)) 629 return AH_FALSE; 630 *resultsize = sizeof(uint16_t); 631 return AH_TRUE; 632#ifdef AH_PRIVATE_DIAG 633 case HAL_DIAG_SETKEY: { 634 const HAL_DIAG_KEYVAL *dk; 635 636 if (argsize != sizeof(HAL_DIAG_KEYVAL)) 637 return AH_FALSE; 638 dk = (const HAL_DIAG_KEYVAL *)args; 639 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix, 640 &dk->dk_keyval, dk->dk_mac, dk->dk_xor); 641 } 642 case HAL_DIAG_RESETKEY: 643 if (argsize != sizeof(uint16_t)) 644 return AH_FALSE; 645 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args); 646#ifdef AH_SUPPORT_WRITE_EEPROM 647 case HAL_DIAG_EEWRITE: { 648 const HAL_DIAG_EEVAL *ee; 649 if (argsize != sizeof(HAL_DIAG_EEVAL)) 650 return AH_FALSE; 651 ee = (const HAL_DIAG_EEVAL *)args; 652 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data); 653 } 654#endif /* AH_SUPPORT_WRITE_EEPROM */ 655#endif /* AH_PRIVATE_DIAG */ 656 case HAL_DIAG_11NCOMPAT: 657 if (argsize == 0) { 658 *resultsize = sizeof(uint32_t); 659 *((uint32_t *)(*result)) = 660 AH_PRIVATE(ah)->ah_11nCompat; 661 } else if (argsize == sizeof(uint32_t)) { 662 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args; 663 } else 664 return AH_FALSE; 665 return AH_TRUE; 666 } 667 return AH_FALSE; 668} 669 670/* 671 * Set the properties of the tx queue with the parameters 672 * from qInfo. 673 */ 674HAL_BOOL 675ath_hal_setTxQProps(struct ath_hal *ah, 676 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo) 677{ 678 uint32_t cw; 679 680 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 681 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, 682 "%s: inactive queue\n", __func__); 683 return AH_FALSE; 684 } 685 /* XXX validate parameters */ 686 qi->tqi_ver = qInfo->tqi_ver; 687 qi->tqi_subtype = qInfo->tqi_subtype; 688 qi->tqi_qflags = qInfo->tqi_qflags; 689 qi->tqi_priority = qInfo->tqi_priority; 690 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT) 691 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255); 692 else 693 qi->tqi_aifs = INIT_AIFS; 694 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) { 695 cw = AH_MIN(qInfo->tqi_cwmin, 1024); 696 /* make sure that the CWmin is of the form (2^n - 1) */ 697 qi->tqi_cwmin = 1; 698 while (qi->tqi_cwmin < cw) 699 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; 700 } else 701 qi->tqi_cwmin = qInfo->tqi_cwmin; 702 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) { 703 cw = AH_MIN(qInfo->tqi_cwmax, 1024); 704 /* make sure that the CWmax is of the form (2^n - 1) */ 705 qi->tqi_cwmax = 1; 706 while (qi->tqi_cwmax < cw) 707 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; 708 } else 709 qi->tqi_cwmax = INIT_CWMAX; 710 /* Set retry limit values */ 711 if (qInfo->tqi_shretry != 0) 712 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15); 713 else 714 qi->tqi_shretry = INIT_SH_RETRY; 715 if (qInfo->tqi_lgretry != 0) 716 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15); 717 else 718 qi->tqi_lgretry = INIT_LG_RETRY; 719 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod; 720 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit; 721 qi->tqi_burstTime = qInfo->tqi_burstTime; 722 qi->tqi_readyTime = qInfo->tqi_readyTime; 723 724 switch (qInfo->tqi_subtype) { 725 case HAL_WME_UPSD: 726 if (qi->tqi_type == HAL_TX_QUEUE_DATA) 727 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS; 728 break; 729 default: 730 break; /* NB: silence compiler */ 731 } 732 return AH_TRUE; 733} 734 735HAL_BOOL 736ath_hal_getTxQProps(struct ath_hal *ah, 737 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi) 738{ 739 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 740 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, 741 "%s: inactive queue\n", __func__); 742 return AH_FALSE; 743 } 744 745 qInfo->tqi_qflags = qi->tqi_qflags; 746 qInfo->tqi_ver = qi->tqi_ver; 747 qInfo->tqi_subtype = qi->tqi_subtype; 748 qInfo->tqi_qflags = qi->tqi_qflags; 749 qInfo->tqi_priority = qi->tqi_priority; 750 qInfo->tqi_aifs = qi->tqi_aifs; 751 qInfo->tqi_cwmin = qi->tqi_cwmin; 752 qInfo->tqi_cwmax = qi->tqi_cwmax; 753 qInfo->tqi_shretry = qi->tqi_shretry; 754 qInfo->tqi_lgretry = qi->tqi_lgretry; 755 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; 756 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; 757 qInfo->tqi_burstTime = qi->tqi_burstTime; 758 qInfo->tqi_readyTime = qi->tqi_readyTime; 759 return AH_TRUE; 760} 761 762 /* 11a Turbo 11b 11g 108g */ 763static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 }; 764 765/* 766 * Read the current channel noise floor and return. 767 * If nf cal hasn't finished, channel noise floor should be 0 768 * and we return a nominal value based on band and frequency. 769 * 770 * NB: This is a private routine used by per-chip code to 771 * implement the ah_getChanNoise method. 772 */ 773int16_t 774ath_hal_getChanNoise(struct ath_hal *ah, HAL_CHANNEL *chan) 775{ 776 HAL_CHANNEL_INTERNAL *ichan; 777 778 ichan = ath_hal_checkchannel(ah, chan); 779 if (ichan == AH_NULL) { 780 HALDEBUG(ah, HAL_DEBUG_NFCAL, 781 "%s: invalid channel %u/0x%x; no mapping\n", 782 __func__, chan->channel, chan->channelFlags); 783 return 0; 784 } 785 if (ichan->rawNoiseFloor == 0) { 786 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); 787 788 HALASSERT(mode < WIRELESS_MODE_MAX); 789 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan); 790 } else 791 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust; 792} 793 794/* 795 * Process all valid raw noise floors into the dBm noise floor values. 796 * Though our device has no reference for a dBm noise floor, we perform 797 * a relative minimization of NF's based on the lowest NF found across a 798 * channel scan. 799 */ 800void 801ath_hal_process_noisefloor(struct ath_hal *ah) 802{ 803 HAL_CHANNEL_INTERNAL *c; 804 int16_t correct2, correct5; 805 int16_t lowest2, lowest5; 806 int i; 807 808 /* 809 * Find the lowest 2GHz and 5GHz noise floor values after adjusting 810 * for statistically recorded NF/channel deviation. 811 */ 812 correct2 = lowest2 = 0; 813 correct5 = lowest5 = 0; 814 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { 815 WIRELESS_MODE mode; 816 int16_t nf; 817 818 c = &AH_PRIVATE(ah)->ah_channels[i]; 819 if (c->rawNoiseFloor >= 0) 820 continue; 821 mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) c); 822 HALASSERT(mode < WIRELESS_MODE_MAX); 823 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] + 824 ath_hal_getNfAdjust(ah, c); 825 if (IS_CHAN_5GHZ(c)) { 826 if (nf < lowest5) { 827 lowest5 = nf; 828 correct5 = NOISE_FLOOR[mode] - 829 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); 830 } 831 } else { 832 if (nf < lowest2) { 833 lowest2 = nf; 834 correct2 = NOISE_FLOOR[mode] - 835 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); 836 } 837 } 838 } 839 840 /* Correct the channels to reach the expected NF value */ 841 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { 842 c = &AH_PRIVATE(ah)->ah_channels[i]; 843 if (c->rawNoiseFloor >= 0) 844 continue; 845 /* Apply correction factor */ 846 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) + 847 (IS_CHAN_5GHZ(c) ? correct5 : correct2); 848 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u/0x%x raw nf %d adjust %d\n", 849 c->channel, c->channelFlags, c->rawNoiseFloor, 850 c->noiseFloorAdjust); 851 } 852} 853 854/* 855 * INI support routines. 856 */ 857 858int 859ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, 860 int col, int regWr) 861{ 862 int r; 863 864 for (r = 0; r < ia->rows; r++) { 865 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), 866 HAL_INI_VAL(ia, r, col)); 867 DMA_YIELD(regWr); 868 } 869 return regWr; 870} 871 872void 873ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col) 874{ 875 int r; 876 877 for (r = 0; r < ia->rows; r++) 878 data[r] = HAL_INI_VAL(ia, r, col); 879} 880 881int 882ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, 883 const uint32_t data[], int regWr) 884{ 885 int r; 886 887 for (r = 0; r < ia->rows; r++) { 888 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]); 889 DMA_YIELD(regWr); 890 } 891 return regWr; 892} 893