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