ah.c revision 239288
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 239288 2012-08-15 07:56:48Z adrian $ 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_HOWL: 113 return "9130"; 114 case AR_XSREV_VERSION_SOWL: 115 return "9160"; 116 case AR_XSREV_VERSION_MERLIN: 117 if (AH_PRIVATE(ah)->ah_ispcie) 118 return "9280"; 119 return "9220"; 120 case AR_XSREV_VERSION_KITE: 121 return "9285"; 122 case AR_XSREV_VERSION_KIWI: 123 if (AH_PRIVATE(ah)->ah_ispcie) 124 return "9287"; 125 return "9227"; 126 } 127 return "????"; 128} 129 130/* 131 * Return the mask of available modes based on the hardware capabilities. 132 */ 133u_int 134ath_hal_getwirelessmodes(struct ath_hal*ah) 135{ 136 return ath_hal_getWirelessModes(ah); 137} 138 139/* linker set of registered RF backends */ 140OS_SET_DECLARE(ah_rfs, struct ath_hal_rf); 141 142/* 143 * Check the set of registered RF backends to see if 144 * any recognize the device as one they can support. 145 */ 146struct ath_hal_rf * 147ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode) 148{ 149 struct ath_hal_rf * const *prf; 150 151 OS_SET_FOREACH(prf, ah_rfs) { 152 struct ath_hal_rf *rf = *prf; 153 if (rf->probe(ah)) 154 return rf; 155 } 156 *ecode = HAL_ENOTSUPP; 157 return AH_NULL; 158} 159 160const char * 161ath_hal_rf_name(struct ath_hal *ah) 162{ 163 switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { 164 case 0: /* 5210 */ 165 return "5110"; /* NB: made up */ 166 case AR_RAD5111_SREV_MAJOR: 167 case AR_RAD5111_SREV_PROD: 168 return "5111"; 169 case AR_RAD2111_SREV_MAJOR: 170 return "2111"; 171 case AR_RAD5112_SREV_MAJOR: 172 case AR_RAD5112_SREV_2_0: 173 case AR_RAD5112_SREV_2_1: 174 return "5112"; 175 case AR_RAD2112_SREV_MAJOR: 176 case AR_RAD2112_SREV_2_0: 177 case AR_RAD2112_SREV_2_1: 178 return "2112"; 179 case AR_RAD2413_SREV_MAJOR: 180 return "2413"; 181 case AR_RAD5413_SREV_MAJOR: 182 return "5413"; 183 case AR_RAD2316_SREV_MAJOR: 184 return "2316"; 185 case AR_RAD2317_SREV_MAJOR: 186 return "2317"; 187 case AR_RAD5424_SREV_MAJOR: 188 return "5424"; 189 190 case AR_RAD5133_SREV_MAJOR: 191 return "5133"; 192 case AR_RAD2133_SREV_MAJOR: 193 return "2133"; 194 case AR_RAD5122_SREV_MAJOR: 195 return "5122"; 196 case AR_RAD2122_SREV_MAJOR: 197 return "2122"; 198 } 199 return "????"; 200} 201 202/* 203 * Poll the register looking for a specific value. 204 */ 205HAL_BOOL 206ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val) 207{ 208#define AH_TIMEOUT 1000 209 return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT); 210#undef AH_TIMEOUT 211} 212 213HAL_BOOL 214ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout) 215{ 216 int i; 217 218 for (i = 0; i < timeout; i++) { 219 if ((OS_REG_READ(ah, reg) & mask) == val) 220 return AH_TRUE; 221 OS_DELAY(10); 222 } 223 HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO, 224 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", 225 __func__, reg, OS_REG_READ(ah, reg), mask, val); 226 return AH_FALSE; 227} 228 229/* 230 * Reverse the bits starting at the low bit for a value of 231 * bit_count in size 232 */ 233uint32_t 234ath_hal_reverseBits(uint32_t val, uint32_t n) 235{ 236 uint32_t retval; 237 int i; 238 239 for (i = 0, retval = 0; i < n; i++) { 240 retval = (retval << 1) | (val & 1); 241 val >>= 1; 242 } 243 return retval; 244} 245 246/* 802.11n related timing definitions */ 247 248#define OFDM_PLCP_BITS 22 249#define HT_L_STF 8 250#define HT_L_LTF 8 251#define HT_L_SIG 4 252#define HT_SIG 8 253#define HT_STF 4 254#define HT_LTF(n) ((n) * 4) 255 256#define HT_RC_2_MCS(_rc) ((_rc) & 0xf) 257#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) 258#define IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS) 259 260/* 261 * Calculate the duration of a packet whether it is 11n or legacy. 262 */ 263uint32_t 264ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen, 265 uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble) 266{ 267 uint8_t rc; 268 int numStreams; 269 270 rc = rates->info[rateix].rateCode; 271 272 /* Legacy rate? Return the old way */ 273 if (! IS_HT_RATE(rc)) 274 return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble); 275 276 /* 11n frame - extract out the number of spatial streams */ 277 numStreams = HT_RC_2_STREAMS(rc); 278 KASSERT(numStreams > 0 && numStreams <= 4, 279 ("number of spatial streams needs to be 1..3: MCS rate 0x%x!", 280 rateix)); 281 282 return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble); 283} 284 285static const uint16_t ht20_bps[32] = { 286 26, 52, 78, 104, 156, 208, 234, 260, 287 52, 104, 156, 208, 312, 416, 468, 520, 288 78, 156, 234, 312, 468, 624, 702, 780, 289 104, 208, 312, 416, 624, 832, 936, 1040 290}; 291static const uint16_t ht40_bps[32] = { 292 54, 108, 162, 216, 324, 432, 486, 540, 293 108, 216, 324, 432, 648, 864, 972, 1080, 294 162, 324, 486, 648, 972, 1296, 1458, 1620, 295 216, 432, 648, 864, 1296, 1728, 1944, 2160 296}; 297 298/* 299 * Calculate the transmit duration of an 11n frame. 300 */ 301uint32_t 302ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams, 303 HAL_BOOL isht40, HAL_BOOL isShortGI) 304{ 305 uint32_t bitsPerSymbol, numBits, numSymbols, txTime; 306 307 KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate)); 308 KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate)); 309 310 if (isht40) 311 bitsPerSymbol = ht40_bps[rate & 0xf]; 312 else 313 bitsPerSymbol = ht20_bps[rate & 0xf]; 314 numBits = OFDM_PLCP_BITS + (frameLen << 3); 315 numSymbols = howmany(numBits, bitsPerSymbol); 316 if (isShortGI) 317 txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */ 318 else 319 txTime = numSymbols * 4; /* 4us */ 320 return txTime + HT_L_STF + HT_L_LTF + 321 HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams); 322} 323 324/* 325 * Compute the time to transmit a frame of length frameLen bytes 326 * using the specified rate, phy, and short preamble setting. 327 */ 328uint16_t 329ath_hal_computetxtime(struct ath_hal *ah, 330 const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix, 331 HAL_BOOL shortPreamble) 332{ 333 uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime; 334 uint32_t kbps; 335 336 /* Warn if this function is called for 11n rates; it should not be! */ 337 if (IS_HT_RATE(rates->info[rateix].rateCode)) 338 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n", 339 __func__, rateix, rates->info[rateix].rateCode); 340 341 kbps = rates->info[rateix].rateKbps; 342 /* 343 * index can be invalid duting dynamic Turbo transitions. 344 * XXX 345 */ 346 if (kbps == 0) 347 return 0; 348 switch (rates->info[rateix].phy) { 349 case IEEE80211_T_CCK: 350 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; 351 if (shortPreamble && rates->info[rateix].shortPreamble) 352 phyTime >>= 1; 353 numBits = frameLen << 3; 354 txTime = CCK_SIFS_TIME + phyTime 355 + ((numBits * 1000)/kbps); 356 break; 357 case IEEE80211_T_OFDM: 358 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; 359 HALASSERT(bitsPerSymbol != 0); 360 361 numBits = OFDM_PLCP_BITS + (frameLen << 3); 362 numSymbols = howmany(numBits, bitsPerSymbol); 363 txTime = OFDM_SIFS_TIME 364 + OFDM_PREAMBLE_TIME 365 + (numSymbols * OFDM_SYMBOL_TIME); 366 break; 367 case IEEE80211_T_OFDM_HALF: 368 bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000; 369 HALASSERT(bitsPerSymbol != 0); 370 371 numBits = OFDM_HALF_PLCP_BITS + (frameLen << 3); 372 numSymbols = howmany(numBits, bitsPerSymbol); 373 txTime = OFDM_HALF_SIFS_TIME 374 + OFDM_HALF_PREAMBLE_TIME 375 + (numSymbols * OFDM_HALF_SYMBOL_TIME); 376 break; 377 case IEEE80211_T_OFDM_QUARTER: 378 bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000; 379 HALASSERT(bitsPerSymbol != 0); 380 381 numBits = OFDM_QUARTER_PLCP_BITS + (frameLen << 3); 382 numSymbols = howmany(numBits, bitsPerSymbol); 383 txTime = OFDM_QUARTER_SIFS_TIME 384 + OFDM_QUARTER_PREAMBLE_TIME 385 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME); 386 break; 387 case IEEE80211_T_TURBO: 388 bitsPerSymbol = (kbps * TURBO_SYMBOL_TIME) / 1000; 389 HALASSERT(bitsPerSymbol != 0); 390 391 numBits = TURBO_PLCP_BITS + (frameLen << 3); 392 numSymbols = howmany(numBits, bitsPerSymbol); 393 txTime = TURBO_SIFS_TIME 394 + TURBO_PREAMBLE_TIME 395 + (numSymbols * TURBO_SYMBOL_TIME); 396 break; 397 default: 398 HALDEBUG(ah, HAL_DEBUG_PHYIO, 399 "%s: unknown phy %u (rate ix %u)\n", 400 __func__, rates->info[rateix].phy, rateix); 401 txTime = 0; 402 break; 403 } 404 return txTime; 405} 406 407typedef enum { 408 WIRELESS_MODE_11a = 0, 409 WIRELESS_MODE_TURBO = 1, 410 WIRELESS_MODE_11b = 2, 411 WIRELESS_MODE_11g = 3, 412 WIRELESS_MODE_108g = 4, 413 414 WIRELESS_MODE_MAX 415} WIRELESS_MODE; 416 417static WIRELESS_MODE 418ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan) 419{ 420 if (IEEE80211_IS_CHAN_B(chan)) 421 return WIRELESS_MODE_11b; 422 if (IEEE80211_IS_CHAN_G(chan)) 423 return WIRELESS_MODE_11g; 424 if (IEEE80211_IS_CHAN_108G(chan)) 425 return WIRELESS_MODE_108g; 426 if (IEEE80211_IS_CHAN_TURBO(chan)) 427 return WIRELESS_MODE_TURBO; 428 return WIRELESS_MODE_11a; 429} 430 431/* 432 * Convert between microseconds and core system clocks. 433 */ 434 /* 11a Turbo 11b 11g 108g */ 435static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 }; 436 437#define CLOCK_FAST_RATE_5GHZ_OFDM 44 438 439u_int 440ath_hal_mac_clks(struct ath_hal *ah, u_int usecs) 441{ 442 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan; 443 u_int clks; 444 445 /* NB: ah_curchan may be null when called attach time */ 446 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */ 447 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) { 448 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM; 449 if (IEEE80211_IS_CHAN_HT40(c)) 450 clks <<= 1; 451 } else if (c != AH_NULL) { 452 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; 453 if (IEEE80211_IS_CHAN_HT40(c)) 454 clks <<= 1; 455 } else 456 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b]; 457 return clks; 458} 459 460u_int 461ath_hal_mac_usec(struct ath_hal *ah, u_int clks) 462{ 463 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan; 464 u_int usec; 465 466 /* NB: ah_curchan may be null when called attach time */ 467 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */ 468 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) { 469 usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM; 470 if (IEEE80211_IS_CHAN_HT40(c)) 471 usec >>= 1; 472 } else if (c != AH_NULL) { 473 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; 474 if (IEEE80211_IS_CHAN_HT40(c)) 475 usec >>= 1; 476 } else 477 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b]; 478 return usec; 479} 480 481/* 482 * Setup a h/w rate table's reverse lookup table and 483 * fill in ack durations. This routine is called for 484 * each rate table returned through the ah_getRateTable 485 * method. The reverse lookup tables are assumed to be 486 * initialized to zero (or at least the first entry). 487 * We use this as a key that indicates whether or not 488 * we've previously setup the reverse lookup table. 489 * 490 * XXX not reentrant, but shouldn't matter 491 */ 492void 493ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt) 494{ 495#define N(a) (sizeof(a)/sizeof(a[0])) 496 int i; 497 498 if (rt->rateCodeToIndex[0] != 0) /* already setup */ 499 return; 500 for (i = 0; i < N(rt->rateCodeToIndex); i++) 501 rt->rateCodeToIndex[i] = (uint8_t) -1; 502 for (i = 0; i < rt->rateCount; i++) { 503 uint8_t code = rt->info[i].rateCode; 504 uint8_t cix = rt->info[i].controlRate; 505 506 HALASSERT(code < N(rt->rateCodeToIndex)); 507 rt->rateCodeToIndex[code] = i; 508 HALASSERT((code | rt->info[i].shortPreamble) < 509 N(rt->rateCodeToIndex)); 510 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i; 511 /* 512 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s 513 * depends on whether they are marked as basic rates; 514 * the static tables are setup with an 11b-compatible 515 * 2Mb/s rate which will work but is suboptimal 516 */ 517 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt, 518 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE); 519 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt, 520 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE); 521 } 522#undef N 523} 524 525HAL_STATUS 526ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 527 uint32_t capability, uint32_t *result) 528{ 529 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 530 531 switch (type) { 532 case HAL_CAP_REG_DMN: /* regulatory domain */ 533 *result = AH_PRIVATE(ah)->ah_currentRD; 534 return HAL_OK; 535 case HAL_CAP_DFS_DMN: /* DFS Domain */ 536 *result = AH_PRIVATE(ah)->ah_dfsDomain; 537 return HAL_OK; 538 case HAL_CAP_CIPHER: /* cipher handled in hardware */ 539 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ 540 return HAL_ENOTSUPP; 541 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ 542 return HAL_ENOTSUPP; 543 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */ 544 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO; 545 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */ 546 return HAL_ENOTSUPP; 547 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ 548 return HAL_ENOTSUPP; 549 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */ 550 *result = pCap->halKeyCacheSize; 551 return HAL_OK; 552 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */ 553 *result = pCap->halTotalQueues; 554 return HAL_OK; 555 case HAL_CAP_VEOL: /* hardware supports virtual EOL */ 556 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP; 557 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */ 558 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK; 559 case HAL_CAP_COMPRESSION: 560 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP; 561 case HAL_CAP_BURST: 562 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP; 563 case HAL_CAP_FASTFRAME: 564 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP; 565 case HAL_CAP_DIAG: /* hardware diagnostic support */ 566 *result = AH_PRIVATE(ah)->ah_diagreg; 567 return HAL_OK; 568 case HAL_CAP_TXPOW: /* global tx power limit */ 569 switch (capability) { 570 case 0: /* facility is supported */ 571 return HAL_OK; 572 case 1: /* current limit */ 573 *result = AH_PRIVATE(ah)->ah_powerLimit; 574 return HAL_OK; 575 case 2: /* current max tx power */ 576 *result = AH_PRIVATE(ah)->ah_maxPowerLevel; 577 return HAL_OK; 578 case 3: /* scale factor */ 579 *result = AH_PRIVATE(ah)->ah_tpScale; 580 return HAL_OK; 581 } 582 return HAL_ENOTSUPP; 583 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */ 584 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP; 585 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ 586 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP; 587 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ 588 return HAL_ENOTSUPP; 589 case HAL_CAP_RFSILENT: /* rfsilent support */ 590 switch (capability) { 591 case 0: /* facility is supported */ 592 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP; 593 case 1: /* current setting */ 594 return AH_PRIVATE(ah)->ah_rfkillEnabled ? 595 HAL_OK : HAL_ENOTSUPP; 596 case 2: /* rfsilent config */ 597 *result = AH_PRIVATE(ah)->ah_rfsilent; 598 return HAL_OK; 599 } 600 return HAL_ENOTSUPP; 601 case HAL_CAP_11D: 602 return HAL_OK; 603 604 case HAL_CAP_HT: 605 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP; 606 case HAL_CAP_GTXTO: 607 return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP; 608 case HAL_CAP_FAST_CC: 609 return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP; 610 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */ 611 *result = pCap->halTxChainMask; 612 return HAL_OK; 613 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */ 614 *result = pCap->halRxChainMask; 615 return HAL_OK; 616 case HAL_CAP_NUM_GPIO_PINS: 617 *result = pCap->halNumGpioPins; 618 return HAL_OK; 619 case HAL_CAP_CST: 620 return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP; 621 case HAL_CAP_RTS_AGGR_LIMIT: 622 *result = pCap->halRtsAggrLimit; 623 return HAL_OK; 624 case HAL_CAP_4ADDR_AGGR: 625 return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP; 626 case HAL_CAP_EXT_CHAN_DFS: 627 return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP; 628 case HAL_CAP_COMBINED_RADAR_RSSI: 629 return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP; 630 case HAL_CAP_AUTO_SLEEP: 631 return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP; 632 case HAL_CAP_MBSSID_AGGR_SUPPORT: 633 return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP; 634 case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */ 635 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP; 636 case HAL_CAP_REG_FLAG: 637 *result = AH_PRIVATE(ah)->ah_currentRDext; 638 return HAL_OK; 639 case HAL_CAP_ENHANCED_DMA_SUPPORT: 640 return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP; 641 case HAL_CAP_NUM_TXMAPS: 642 *result = pCap->halNumTxMaps; 643 return HAL_OK; 644 case HAL_CAP_TXDESCLEN: 645 *result = pCap->halTxDescLen; 646 return HAL_OK; 647 case HAL_CAP_TXSTATUSLEN: 648 *result = pCap->halTxStatusLen; 649 return HAL_OK; 650 case HAL_CAP_RXSTATUSLEN: 651 *result = pCap->halRxStatusLen; 652 return HAL_OK; 653 case HAL_CAP_RXFIFODEPTH: 654 switch (capability) { 655 case HAL_RX_QUEUE_HP: 656 *result = pCap->halRxHpFifoDepth; 657 return HAL_OK; 658 case HAL_RX_QUEUE_LP: 659 *result = pCap->halRxLpFifoDepth; 660 return HAL_OK; 661 default: 662 return HAL_ENOTSUPP; 663 } 664 case HAL_CAP_RXBUFSIZE: 665 case HAL_CAP_NUM_MR_RETRIES: 666 *result = pCap->halNumMRRetries; 667 return HAL_OK; 668 case HAL_CAP_BT_COEX: 669 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP; 670 case HAL_CAP_HT20_SGI: 671 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP; 672 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */ 673 *result = pCap->halTstampPrecision; 674 return HAL_OK; 675 case HAL_CAP_ENHANCED_DFS_SUPPORT: 676 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP; 677 678 /* FreeBSD-specific entries for now */ 679 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ 680 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP; 681 case HAL_CAP_INTRMASK: /* mask of supported interrupts */ 682 *result = pCap->halIntrMask; 683 return HAL_OK; 684 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */ 685 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP; 686 case HAL_CAP_STREAMS: /* number of 11n spatial streams */ 687 switch (capability) { 688 case 0: /* TX */ 689 *result = pCap->halTxStreams; 690 return HAL_OK; 691 case 1: /* RX */ 692 *result = pCap->halRxStreams; 693 return HAL_OK; 694 default: 695 return HAL_ENOTSUPP; 696 } 697 case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */ 698 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP; 699 case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */ 700 return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP; 701 case HAL_CAP_BB_READ_WAR: /* Baseband read WAR */ 702 return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP; 703 case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */ 704 return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP; 705 706 default: 707 return HAL_EINVAL; 708 } 709} 710 711HAL_BOOL 712ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 713 uint32_t capability, uint32_t setting, HAL_STATUS *status) 714{ 715 716 switch (type) { 717 case HAL_CAP_TXPOW: 718 switch (capability) { 719 case 3: 720 if (setting <= HAL_TP_SCALE_MIN) { 721 AH_PRIVATE(ah)->ah_tpScale = setting; 722 return AH_TRUE; 723 } 724 break; 725 } 726 break; 727 case HAL_CAP_RFSILENT: /* rfsilent support */ 728 /* 729 * NB: allow even if halRfSilentSupport is false 730 * in case the EEPROM is misprogrammed. 731 */ 732 switch (capability) { 733 case 1: /* current setting */ 734 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0); 735 return AH_TRUE; 736 case 2: /* rfsilent config */ 737 /* XXX better done per-chip for validation? */ 738 AH_PRIVATE(ah)->ah_rfsilent = setting; 739 return AH_TRUE; 740 } 741 break; 742 case HAL_CAP_REG_DMN: /* regulatory domain */ 743 AH_PRIVATE(ah)->ah_currentRD = setting; 744 return AH_TRUE; 745 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ 746 AH_PRIVATE(ah)->ah_rxornIsFatal = setting; 747 return AH_TRUE; 748 default: 749 break; 750 } 751 if (status) 752 *status = HAL_EINVAL; 753 return AH_FALSE; 754} 755 756/* 757 * Common support for getDiagState method. 758 */ 759 760static u_int 761ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs, 762 void *dstbuf, int space) 763{ 764 uint32_t *dp = dstbuf; 765 int i; 766 767 for (i = 0; space >= 2*sizeof(uint32_t); i++) { 768 u_int r = regs[i].start; 769 u_int e = regs[i].end; 770 *dp++ = (r<<16) | e; 771 space -= sizeof(uint32_t); 772 do { 773 *dp++ = OS_REG_READ(ah, r); 774 r += sizeof(uint32_t); 775 space -= sizeof(uint32_t); 776 } while (r <= e && space >= sizeof(uint32_t)); 777 } 778 return (char *) dp - (char *) dstbuf; 779} 780 781static void 782ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space) 783{ 784 while (space >= sizeof(HAL_REGWRITE)) { 785 OS_REG_WRITE(ah, regs->addr, regs->value); 786 regs++, space -= sizeof(HAL_REGWRITE); 787 } 788} 789 790HAL_BOOL 791ath_hal_getdiagstate(struct ath_hal *ah, int request, 792 const void *args, uint32_t argsize, 793 void **result, uint32_t *resultsize) 794{ 795 switch (request) { 796 case HAL_DIAG_REVS: 797 *result = &AH_PRIVATE(ah)->ah_devid; 798 *resultsize = sizeof(HAL_REVS); 799 return AH_TRUE; 800 case HAL_DIAG_REGS: 801 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize); 802 return AH_TRUE; 803 case HAL_DIAG_SETREGS: 804 ath_hal_setregs(ah, args, argsize); 805 *resultsize = 0; 806 return AH_TRUE; 807 case HAL_DIAG_FATALERR: 808 *result = &AH_PRIVATE(ah)->ah_fatalState[0]; 809 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState); 810 return AH_TRUE; 811 case HAL_DIAG_EEREAD: 812 if (argsize != sizeof(uint16_t)) 813 return AH_FALSE; 814 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result)) 815 return AH_FALSE; 816 *resultsize = sizeof(uint16_t); 817 return AH_TRUE; 818#ifdef AH_PRIVATE_DIAG 819 case HAL_DIAG_SETKEY: { 820 const HAL_DIAG_KEYVAL *dk; 821 822 if (argsize != sizeof(HAL_DIAG_KEYVAL)) 823 return AH_FALSE; 824 dk = (const HAL_DIAG_KEYVAL *)args; 825 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix, 826 &dk->dk_keyval, dk->dk_mac, dk->dk_xor); 827 } 828 case HAL_DIAG_RESETKEY: 829 if (argsize != sizeof(uint16_t)) 830 return AH_FALSE; 831 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args); 832#ifdef AH_SUPPORT_WRITE_EEPROM 833 case HAL_DIAG_EEWRITE: { 834 const HAL_DIAG_EEVAL *ee; 835 if (argsize != sizeof(HAL_DIAG_EEVAL)) 836 return AH_FALSE; 837 ee = (const HAL_DIAG_EEVAL *)args; 838 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data); 839 } 840#endif /* AH_SUPPORT_WRITE_EEPROM */ 841#endif /* AH_PRIVATE_DIAG */ 842 case HAL_DIAG_11NCOMPAT: 843 if (argsize == 0) { 844 *resultsize = sizeof(uint32_t); 845 *((uint32_t *)(*result)) = 846 AH_PRIVATE(ah)->ah_11nCompat; 847 } else if (argsize == sizeof(uint32_t)) { 848 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args; 849 } else 850 return AH_FALSE; 851 return AH_TRUE; 852 } 853 return AH_FALSE; 854} 855 856/* 857 * Set the properties of the tx queue with the parameters 858 * from qInfo. 859 */ 860HAL_BOOL 861ath_hal_setTxQProps(struct ath_hal *ah, 862 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo) 863{ 864 uint32_t cw; 865 866 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 867 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, 868 "%s: inactive queue\n", __func__); 869 return AH_FALSE; 870 } 871 /* XXX validate parameters */ 872 qi->tqi_ver = qInfo->tqi_ver; 873 qi->tqi_subtype = qInfo->tqi_subtype; 874 qi->tqi_qflags = qInfo->tqi_qflags; 875 qi->tqi_priority = qInfo->tqi_priority; 876 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT) 877 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255); 878 else 879 qi->tqi_aifs = INIT_AIFS; 880 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) { 881 cw = AH_MIN(qInfo->tqi_cwmin, 1024); 882 /* make sure that the CWmin is of the form (2^n - 1) */ 883 qi->tqi_cwmin = 1; 884 while (qi->tqi_cwmin < cw) 885 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; 886 } else 887 qi->tqi_cwmin = qInfo->tqi_cwmin; 888 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) { 889 cw = AH_MIN(qInfo->tqi_cwmax, 1024); 890 /* make sure that the CWmax is of the form (2^n - 1) */ 891 qi->tqi_cwmax = 1; 892 while (qi->tqi_cwmax < cw) 893 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; 894 } else 895 qi->tqi_cwmax = INIT_CWMAX; 896 /* Set retry limit values */ 897 if (qInfo->tqi_shretry != 0) 898 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15); 899 else 900 qi->tqi_shretry = INIT_SH_RETRY; 901 if (qInfo->tqi_lgretry != 0) 902 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15); 903 else 904 qi->tqi_lgretry = INIT_LG_RETRY; 905 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod; 906 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit; 907 qi->tqi_burstTime = qInfo->tqi_burstTime; 908 qi->tqi_readyTime = qInfo->tqi_readyTime; 909 910 switch (qInfo->tqi_subtype) { 911 case HAL_WME_UPSD: 912 if (qi->tqi_type == HAL_TX_QUEUE_DATA) 913 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS; 914 break; 915 default: 916 break; /* NB: silence compiler */ 917 } 918 return AH_TRUE; 919} 920 921HAL_BOOL 922ath_hal_getTxQProps(struct ath_hal *ah, 923 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi) 924{ 925 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 926 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, 927 "%s: inactive queue\n", __func__); 928 return AH_FALSE; 929 } 930 931 qInfo->tqi_qflags = qi->tqi_qflags; 932 qInfo->tqi_ver = qi->tqi_ver; 933 qInfo->tqi_subtype = qi->tqi_subtype; 934 qInfo->tqi_qflags = qi->tqi_qflags; 935 qInfo->tqi_priority = qi->tqi_priority; 936 qInfo->tqi_aifs = qi->tqi_aifs; 937 qInfo->tqi_cwmin = qi->tqi_cwmin; 938 qInfo->tqi_cwmax = qi->tqi_cwmax; 939 qInfo->tqi_shretry = qi->tqi_shretry; 940 qInfo->tqi_lgretry = qi->tqi_lgretry; 941 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; 942 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; 943 qInfo->tqi_burstTime = qi->tqi_burstTime; 944 qInfo->tqi_readyTime = qi->tqi_readyTime; 945 return AH_TRUE; 946} 947 948 /* 11a Turbo 11b 11g 108g */ 949static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 }; 950 951/* 952 * Read the current channel noise floor and return. 953 * If nf cal hasn't finished, channel noise floor should be 0 954 * and we return a nominal value based on band and frequency. 955 * 956 * NB: This is a private routine used by per-chip code to 957 * implement the ah_getChanNoise method. 958 */ 959int16_t 960ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan) 961{ 962 HAL_CHANNEL_INTERNAL *ichan; 963 964 ichan = ath_hal_checkchannel(ah, chan); 965 if (ichan == AH_NULL) { 966 HALDEBUG(ah, HAL_DEBUG_NFCAL, 967 "%s: invalid channel %u/0x%x; no mapping\n", 968 __func__, chan->ic_freq, chan->ic_flags); 969 return 0; 970 } 971 if (ichan->rawNoiseFloor == 0) { 972 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); 973 974 HALASSERT(mode < WIRELESS_MODE_MAX); 975 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan); 976 } else 977 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust; 978} 979 980/* 981 * Fetch the current setup of ctl/ext noise floor values. 982 * 983 * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply 984 * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust(). 985 * 986 * The caller must supply ctl/ext NF arrays which are at least 987 * AH_MIMO_MAX_CHAINS entries long. 988 */ 989int 990ath_hal_get_mimo_chan_noise(struct ath_hal *ah, 991 const struct ieee80211_channel *chan, int16_t *nf_ctl, 992 int16_t *nf_ext) 993{ 994#ifdef AH_SUPPORT_AR5416 995 HAL_CHANNEL_INTERNAL *ichan; 996 int i; 997 998 ichan = ath_hal_checkchannel(ah, chan); 999 if (ichan == AH_NULL) { 1000 HALDEBUG(ah, HAL_DEBUG_NFCAL, 1001 "%s: invalid channel %u/0x%x; no mapping\n", 1002 __func__, chan->ic_freq, chan->ic_flags); 1003 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { 1004 nf_ctl[i] = nf_ext[i] = 0; 1005 } 1006 return 0; 1007 } 1008 1009 /* Return 0 if there's no valid MIMO values (yet) */ 1010 if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) { 1011 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { 1012 nf_ctl[i] = nf_ext[i] = 0; 1013 } 1014 return 0; 1015 } 1016 if (ichan->rawNoiseFloor == 0) { 1017 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); 1018 HALASSERT(mode < WIRELESS_MODE_MAX); 1019 /* 1020 * See the comment below - this could cause issues for 1021 * stations which have a very low RSSI, below the 1022 * 'normalised' NF values in NOISE_FLOOR[]. 1023 */ 1024 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { 1025 nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] + 1026 ath_hal_getNfAdjust(ah, ichan); 1027 } 1028 return 1; 1029 } else { 1030 /* 1031 * The value returned here from a MIMO radio is presumed to be 1032 * "good enough" as a NF calculation. As RSSI values are calculated 1033 * against this, an adjusted NF may be higher than the RSSI value 1034 * returned from a vary weak station, resulting in an obscenely 1035 * high signal strength calculation being returned. 1036 * 1037 * This should be re-evaluated at a later date, along with any 1038 * signal strength calculations which are made. Quite likely the 1039 * RSSI values will need to be adjusted to ensure the calculations 1040 * don't "wrap" when RSSI is less than the "adjusted" NF value. 1041 * ("Adjust" here is via ichan->noiseFloorAdjust.) 1042 */ 1043 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { 1044 nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan); 1045 nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan); 1046 } 1047 return 1; 1048 } 1049#else 1050 return 0; 1051#endif /* AH_SUPPORT_AR5416 */ 1052} 1053 1054/* 1055 * Process all valid raw noise floors into the dBm noise floor values. 1056 * Though our device has no reference for a dBm noise floor, we perform 1057 * a relative minimization of NF's based on the lowest NF found across a 1058 * channel scan. 1059 */ 1060void 1061ath_hal_process_noisefloor(struct ath_hal *ah) 1062{ 1063 HAL_CHANNEL_INTERNAL *c; 1064 int16_t correct2, correct5; 1065 int16_t lowest2, lowest5; 1066 int i; 1067 1068 /* 1069 * Find the lowest 2GHz and 5GHz noise floor values after adjusting 1070 * for statistically recorded NF/channel deviation. 1071 */ 1072 correct2 = lowest2 = 0; 1073 correct5 = lowest5 = 0; 1074 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { 1075 WIRELESS_MODE mode; 1076 int16_t nf; 1077 1078 c = &AH_PRIVATE(ah)->ah_channels[i]; 1079 if (c->rawNoiseFloor >= 0) 1080 continue; 1081 /* XXX can't identify proper mode */ 1082 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g; 1083 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] + 1084 ath_hal_getNfAdjust(ah, c); 1085 if (IS_CHAN_5GHZ(c)) { 1086 if (nf < lowest5) { 1087 lowest5 = nf; 1088 correct5 = NOISE_FLOOR[mode] - 1089 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); 1090 } 1091 } else { 1092 if (nf < lowest2) { 1093 lowest2 = nf; 1094 correct2 = NOISE_FLOOR[mode] - 1095 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); 1096 } 1097 } 1098 } 1099 1100 /* Correct the channels to reach the expected NF value */ 1101 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { 1102 c = &AH_PRIVATE(ah)->ah_channels[i]; 1103 if (c->rawNoiseFloor >= 0) 1104 continue; 1105 /* Apply correction factor */ 1106 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) + 1107 (IS_CHAN_5GHZ(c) ? correct5 : correct2); 1108 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n", 1109 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust); 1110 } 1111} 1112 1113/* 1114 * INI support routines. 1115 */ 1116 1117int 1118ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, 1119 int col, int regWr) 1120{ 1121 int r; 1122 1123 HALASSERT(col < ia->cols); 1124 for (r = 0; r < ia->rows; r++) { 1125 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), 1126 HAL_INI_VAL(ia, r, col)); 1127 1128 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */ 1129 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900) 1130 OS_DELAY(100); 1131 1132 DMA_YIELD(regWr); 1133 } 1134 return regWr; 1135} 1136 1137void 1138ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col) 1139{ 1140 int r; 1141 1142 HALASSERT(col < ia->cols); 1143 for (r = 0; r < ia->rows; r++) 1144 data[r] = HAL_INI_VAL(ia, r, col); 1145} 1146 1147int 1148ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, 1149 const uint32_t data[], int regWr) 1150{ 1151 int r; 1152 1153 for (r = 0; r < ia->rows; r++) { 1154 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]); 1155 DMA_YIELD(regWr); 1156 } 1157 return regWr; 1158} 1159 1160/* 1161 * These are EEPROM board related routines which should likely live in 1162 * a helper library of some sort. 1163 */ 1164 1165/************************************************************** 1166 * ath_ee_getLowerUppderIndex 1167 * 1168 * Return indices surrounding the value in sorted integer lists. 1169 * Requirement: the input list must be monotonically increasing 1170 * and populated up to the list size 1171 * Returns: match is set if an index in the array matches exactly 1172 * or a the target is before or after the range of the array. 1173 */ 1174HAL_BOOL 1175ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize, 1176 uint16_t *indexL, uint16_t *indexR) 1177{ 1178 uint16_t i; 1179 1180 /* 1181 * Check first and last elements for beyond ordered array cases. 1182 */ 1183 if (target <= pList[0]) { 1184 *indexL = *indexR = 0; 1185 return AH_TRUE; 1186 } 1187 if (target >= pList[listSize-1]) { 1188 *indexL = *indexR = (uint16_t)(listSize - 1); 1189 return AH_TRUE; 1190 } 1191 1192 /* look for value being near or between 2 values in list */ 1193 for (i = 0; i < listSize - 1; i++) { 1194 /* 1195 * If value is close to the current value of the list 1196 * then target is not between values, it is one of the values 1197 */ 1198 if (pList[i] == target) { 1199 *indexL = *indexR = i; 1200 return AH_TRUE; 1201 } 1202 /* 1203 * Look for value being between current value and next value 1204 * if so return these 2 values 1205 */ 1206 if (target < pList[i + 1]) { 1207 *indexL = i; 1208 *indexR = (uint16_t)(i + 1); 1209 return AH_FALSE; 1210 } 1211 } 1212 HALASSERT(0); 1213 *indexL = *indexR = 0; 1214 return AH_FALSE; 1215} 1216 1217/************************************************************** 1218 * ath_ee_FillVpdTable 1219 * 1220 * Fill the Vpdlist for indices Pmax-Pmin 1221 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4 1222 */ 1223HAL_BOOL 1224ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, 1225 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList) 1226{ 1227 uint16_t i, k; 1228 uint8_t currPwr = pwrMin; 1229 uint16_t idxL, idxR; 1230 1231 HALASSERT(pwrMax > pwrMin); 1232 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { 1233 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts, 1234 &(idxL), &(idxR)); 1235 if (idxR < 1) 1236 idxR = 1; /* extrapolate below */ 1237 if (idxL == numIntercepts - 1) 1238 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */ 1239 if (pPwrList[idxL] == pPwrList[idxR]) 1240 k = pVpdList[idxL]; 1241 else 1242 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / 1243 (pPwrList[idxR] - pPwrList[idxL]) ); 1244 HALASSERT(k < 256); 1245 pRetVpdList[i] = (uint8_t)k; 1246 currPwr += 2; /* half dB steps */ 1247 } 1248 1249 return AH_TRUE; 1250} 1251 1252/************************************************************************** 1253 * ath_ee_interpolate 1254 * 1255 * Returns signed interpolated or the scaled up interpolated value 1256 */ 1257int16_t 1258ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, 1259 int16_t targetLeft, int16_t targetRight) 1260{ 1261 int16_t rv; 1262 1263 if (srcRight == srcLeft) { 1264 rv = targetLeft; 1265 } else { 1266 rv = (int16_t)( ((target - srcLeft) * targetRight + 1267 (srcRight - target) * targetLeft) / (srcRight - srcLeft) ); 1268 } 1269 return rv; 1270} 1271 1272/* 1273 * Adjust the TSF. 1274 */ 1275void 1276ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta) 1277{ 1278 /* XXX handle wrap/overflow */ 1279 OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta); 1280} 1281 1282/* 1283 * Enable or disable CCA. 1284 */ 1285void 1286ath_hal_setcca(struct ath_hal *ah, int ena) 1287{ 1288 /* 1289 * NB: fill me in; this is not provided by default because disabling 1290 * CCA in most locales violates regulatory. 1291 */ 1292} 1293 1294/* 1295 * Get CCA setting. 1296 */ 1297int 1298ath_hal_getcca(struct ath_hal *ah) 1299{ 1300 u_int32_t diag; 1301 if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK) 1302 return 1; 1303 return ((diag & 0x500000) == 0); 1304} 1305 1306/* 1307 * This routine is only needed when supporting EEPROM-in-RAM setups 1308 * (eg embedded SoCs and on-board PCI/PCIe devices.) 1309 */ 1310/* NB: This is in 16 bit words; not bytes */ 1311/* XXX This doesn't belong here! */ 1312#define ATH_DATA_EEPROM_SIZE 2048 1313 1314HAL_BOOL 1315ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data) 1316{ 1317 if (ah->ah_eepromdata == AH_NULL) { 1318 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__); 1319 return AH_FALSE; 1320 } 1321 if (off > ATH_DATA_EEPROM_SIZE) { 1322 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n", 1323 __func__, off, ATH_DATA_EEPROM_SIZE); 1324 return AH_FALSE; 1325 } 1326 (*data) = ah->ah_eepromdata[off]; 1327 return AH_TRUE; 1328} 1329