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