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