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