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