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$ 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 */ 29 OS_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 */ 35 const char* 36 ath_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 */ 55 struct ath_hal* 56 ath_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 84 const char * 85 ath_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 */ 133 u_int 134 ath_hal_getwirelessmodes(struct ath_hal*ah) 135 { 136 return ath_hal_getWirelessModes(ah); 137 } 138 139 /* linker set of registered RF backends */ 140 OS_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 */ 146 struct ath_hal_rf * 147 ath_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 160 const char * 161 ath_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 */ 205 HAL_BOOL 206 ath_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 213 HAL_BOOL 214 ath_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 */ 233 uint32_t 234 ath_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 */ 263 uint32_t 264 ath_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 */ 287 uint32_t 288 ath_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 */ 322 uint16_t 323 ath_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 401 typedef 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 411 static WIRELESS_MODE 412 ath_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 */ 429 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 }; 430 431 #define CLOCK_FAST_RATE_5GHZ_OFDM 44 432 433 u_int 434 ath_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 454 u_int 455 ath_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 */ 486 void 487 ath_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 519 HAL_STATUS 520 ath_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_BT_COEX: 634 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP; 635 case HAL_CAP_HT20_SGI: 636 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP; 637 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */ 638 *result = pCap->halTstampPrecision; 639 return HAL_OK; 640 case HAL_CAP_ENHANCED_DFS_SUPPORT: 641 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP; 642 643 /* FreeBSD-specific entries for now */ 644 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ 645 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP; 646 case HAL_CAP_INTRMASK: /* mask of supported interrupts */ 647 *result = pCap->halIntrMask; 648 return HAL_OK; 649 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */ 650 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP; 651 case HAL_CAP_STREAMS: /* number of 11n spatial streams */ 652 switch (capability) { 653 case 0: /* TX */ 654 *result = pCap->halTxStreams; 655 return HAL_OK; 656 case 1: /* RX */ 657 *result = pCap->halRxStreams; 658 return HAL_OK; 659 default: 660 return HAL_ENOTSUPP; 661 } 662 case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */ 663 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP; 664 case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */ 665 return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP; 666 case HAL_CAP_BB_READ_WAR: /* Baseband read WAR */ 667 return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP; 668 case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */ 669 return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP; 670 default: 671 return HAL_EINVAL; 672 } 673 } 674 675 HAL_BOOL 676 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 677 uint32_t capability, uint32_t setting, HAL_STATUS *status) 678 { 679 680 switch (type) { 681 case HAL_CAP_TXPOW: 682 switch (capability) { 683 case 3: 684 if (setting <= HAL_TP_SCALE_MIN) { 685 AH_PRIVATE(ah)->ah_tpScale = setting; 686 return AH_TRUE; 687 } 688 break; 689 } 690 break; 691 case HAL_CAP_RFSILENT: /* rfsilent support */ 692 /* 693 * NB: allow even if halRfSilentSupport is false 694 * in case the EEPROM is misprogrammed. 695 */ 696 switch (capability) { 697 case 1: /* current setting */ 698 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0); 699 return AH_TRUE; 700 case 2: /* rfsilent config */ 701 /* XXX better done per-chip for validation? */ 702 AH_PRIVATE(ah)->ah_rfsilent = setting; 703 return AH_TRUE; 704 } 705 break; 706 case HAL_CAP_REG_DMN: /* regulatory domain */ 707 AH_PRIVATE(ah)->ah_currentRD = setting; 708 return AH_TRUE; 709 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ 710 AH_PRIVATE(ah)->ah_rxornIsFatal = setting; 711 return AH_TRUE; 712 default: 713 break; 714 } 715 if (status) 716 *status = HAL_EINVAL; 717 return AH_FALSE; 718 } 719 720 /* 721 * Common support for getDiagState method. 722 */ 723 724 static u_int 725 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs, 726 void *dstbuf, int space) 727 { 728 uint32_t *dp = dstbuf; 729 int i; 730 731 for (i = 0; space >= 2*sizeof(uint32_t); i++) { 732 u_int r = regs[i].start; 733 u_int e = regs[i].end; 734 *dp++ = (r<<16) | e; 735 space -= sizeof(uint32_t); 736 do { 737 *dp++ = OS_REG_READ(ah, r); 738 r += sizeof(uint32_t); 739 space -= sizeof(uint32_t); 740 } while (r <= e && space >= sizeof(uint32_t)); 741 } 742 return (char *) dp - (char *) dstbuf; 743 } 744 745 static void 746 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space) 747 { 748 while (space >= sizeof(HAL_REGWRITE)) { 749 OS_REG_WRITE(ah, regs->addr, regs->value); 750 regs++, space -= sizeof(HAL_REGWRITE); 751 } 752 } 753 754 HAL_BOOL 755 ath_hal_getdiagstate(struct ath_hal *ah, int request, 756 const void *args, uint32_t argsize, 757 void **result, uint32_t *resultsize) 758 { 759 switch (request) { 760 case HAL_DIAG_REVS: 761 *result = &AH_PRIVATE(ah)->ah_devid; 762 *resultsize = sizeof(HAL_REVS); 763 return AH_TRUE; 764 case HAL_DIAG_REGS: 765 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize); 766 return AH_TRUE; 767 case HAL_DIAG_SETREGS: 768 ath_hal_setregs(ah, args, argsize); 769 *resultsize = 0; 770 return AH_TRUE; 771 case HAL_DIAG_FATALERR: 772 *result = &AH_PRIVATE(ah)->ah_fatalState[0]; 773 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState); 774 return AH_TRUE; 775 case HAL_DIAG_EEREAD: 776 if (argsize != sizeof(uint16_t)) 777 return AH_FALSE; 778 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result)) 779 return AH_FALSE; 780 *resultsize = sizeof(uint16_t); 781 return AH_TRUE; 782 #ifdef AH_PRIVATE_DIAG 783 case HAL_DIAG_SETKEY: { 784 const HAL_DIAG_KEYVAL *dk; 785 786 if (argsize != sizeof(HAL_DIAG_KEYVAL)) 787 return AH_FALSE; 788 dk = (const HAL_DIAG_KEYVAL *)args; 789 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix, 790 &dk->dk_keyval, dk->dk_mac, dk->dk_xor); 791 } 792 case HAL_DIAG_RESETKEY: 793 if (argsize != sizeof(uint16_t)) 794 return AH_FALSE; 795 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args); 796 #ifdef AH_SUPPORT_WRITE_EEPROM 797 case HAL_DIAG_EEWRITE: { 798 const HAL_DIAG_EEVAL *ee; 799 if (argsize != sizeof(HAL_DIAG_EEVAL)) 800 return AH_FALSE; 801 ee = (const HAL_DIAG_EEVAL *)args; 802 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data); 803 } 804 #endif /* AH_SUPPORT_WRITE_EEPROM */ 805 #endif /* AH_PRIVATE_DIAG */ 806 case HAL_DIAG_11NCOMPAT: 807 if (argsize == 0) { 808 *resultsize = sizeof(uint32_t); 809 *((uint32_t *)(*result)) = 810 AH_PRIVATE(ah)->ah_11nCompat; 811 } else if (argsize == sizeof(uint32_t)) { 812 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args; 813 } else 814 return AH_FALSE; 815 return AH_TRUE; 816 } 817 return AH_FALSE; 818 } 819 820 /* 821 * Set the properties of the tx queue with the parameters 822 * from qInfo. 823 */ 824 HAL_BOOL 825 ath_hal_setTxQProps(struct ath_hal *ah, 826 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo) 827 { 828 uint32_t cw; 829 830 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 831 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, 832 "%s: inactive queue\n", __func__); 833 return AH_FALSE; 834 } 835 /* XXX validate parameters */ 836 qi->tqi_ver = qInfo->tqi_ver; 837 qi->tqi_subtype = qInfo->tqi_subtype; 838 qi->tqi_qflags = qInfo->tqi_qflags; 839 qi->tqi_priority = qInfo->tqi_priority; 840 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT) 841 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255); 842 else 843 qi->tqi_aifs = INIT_AIFS; 844 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) { 845 cw = AH_MIN(qInfo->tqi_cwmin, 1024); 846 /* make sure that the CWmin is of the form (2^n - 1) */ 847 qi->tqi_cwmin = 1; 848 while (qi->tqi_cwmin < cw) 849 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; 850 } else 851 qi->tqi_cwmin = qInfo->tqi_cwmin; 852 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) { 853 cw = AH_MIN(qInfo->tqi_cwmax, 1024); 854 /* make sure that the CWmax is of the form (2^n - 1) */ 855 qi->tqi_cwmax = 1; 856 while (qi->tqi_cwmax < cw) 857 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; 858 } else 859 qi->tqi_cwmax = INIT_CWMAX; 860 /* Set retry limit values */ 861 if (qInfo->tqi_shretry != 0) 862 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15); 863 else 864 qi->tqi_shretry = INIT_SH_RETRY; 865 if (qInfo->tqi_lgretry != 0) 866 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15); 867 else 868 qi->tqi_lgretry = INIT_LG_RETRY; 869 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod; 870 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit; 871 qi->tqi_burstTime = qInfo->tqi_burstTime; 872 qi->tqi_readyTime = qInfo->tqi_readyTime; 873 874 switch (qInfo->tqi_subtype) { 875 case HAL_WME_UPSD: 876 if (qi->tqi_type == HAL_TX_QUEUE_DATA) 877 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS; 878 break; 879 default: 880 break; /* NB: silence compiler */ 881 } 882 return AH_TRUE; 883 } 884 885 HAL_BOOL 886 ath_hal_getTxQProps(struct ath_hal *ah, 887 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi) 888 { 889 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 890 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, 891 "%s: inactive queue\n", __func__); 892 return AH_FALSE; 893 } 894 895 qInfo->tqi_qflags = qi->tqi_qflags; 896 qInfo->tqi_ver = qi->tqi_ver; 897 qInfo->tqi_subtype = qi->tqi_subtype; 898 qInfo->tqi_qflags = qi->tqi_qflags; 899 qInfo->tqi_priority = qi->tqi_priority; 900 qInfo->tqi_aifs = qi->tqi_aifs; 901 qInfo->tqi_cwmin = qi->tqi_cwmin; 902 qInfo->tqi_cwmax = qi->tqi_cwmax; 903 qInfo->tqi_shretry = qi->tqi_shretry; 904 qInfo->tqi_lgretry = qi->tqi_lgretry; 905 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; 906 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; 907 qInfo->tqi_burstTime = qi->tqi_burstTime; 908 qInfo->tqi_readyTime = qi->tqi_readyTime; 909 return AH_TRUE; 910 } 911 912 /* 11a Turbo 11b 11g 108g */ 913 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 }; 914 915 /* 916 * Read the current channel noise floor and return. 917 * If nf cal hasn't finished, channel noise floor should be 0 918 * and we return a nominal value based on band and frequency. 919 * 920 * NB: This is a private routine used by per-chip code to 921 * implement the ah_getChanNoise method. 922 */ 923 int16_t 924 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan) 925 { 926 HAL_CHANNEL_INTERNAL *ichan; 927 928 ichan = ath_hal_checkchannel(ah, chan); 929 if (ichan == AH_NULL) { 930 HALDEBUG(ah, HAL_DEBUG_NFCAL, 931 "%s: invalid channel %u/0x%x; no mapping\n", 932 __func__, chan->ic_freq, chan->ic_flags); 933 return 0; 934 } 935 if (ichan->rawNoiseFloor == 0) { 936 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); 937 938 HALASSERT(mode < WIRELESS_MODE_MAX); 939 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan); 940 } else 941 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust; 942 } 943 944 /* 945 * Fetch the current setup of ctl/ext noise floor values. 946 * 947 * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply 948 * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust(). 949 * 950 * The caller must supply ctl/ext NF arrays which are at least 951 * AH_MIMO_MAX_CHAINS entries long. 952 */ 953 int 954 ath_hal_get_mimo_chan_noise(struct ath_hal *ah, 955 const struct ieee80211_channel *chan, int16_t *nf_ctl, 956 int16_t *nf_ext) 957 { 958 #ifdef AH_SUPPORT_AR5416 959 HAL_CHANNEL_INTERNAL *ichan; 960 int i; 961 962 ichan = ath_hal_checkchannel(ah, chan); 963 if (ichan == AH_NULL) { 964 HALDEBUG(ah, HAL_DEBUG_NFCAL, 965 "%s: invalid channel %u/0x%x; no mapping\n", 966 __func__, chan->ic_freq, chan->ic_flags); 967 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { 968 nf_ctl[i] = nf_ext[i] = 0; 969 } 970 return 0; 971 } 972 973 /* Return 0 if there's no valid MIMO values (yet) */ 974 if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) { 975 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { 976 nf_ctl[i] = nf_ext[i] = 0; 977 } 978 return 0; 979 } 980 if (ichan->rawNoiseFloor == 0) { 981 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); 982 HALASSERT(mode < WIRELESS_MODE_MAX); 983 /* 984 * See the comment below - this could cause issues for 985 * stations which have a very low RSSI, below the 986 * 'normalised' NF values in NOISE_FLOOR[]. 987 */ 988 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { 989 nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] + 990 ath_hal_getNfAdjust(ah, ichan); 991 } 992 return 1; 993 } else { 994 /* 995 * The value returned here from a MIMO radio is presumed to be 996 * "good enough" as a NF calculation. As RSSI values are calculated 997 * against this, an adjusted NF may be higher than the RSSI value 998 * returned from a vary weak station, resulting in an obscenely 999 * high signal strength calculation being returned. 1000 * 1001 * This should be re-evaluated at a later date, along with any 1002 * signal strength calculations which are made. Quite likely the 1003 * RSSI values will need to be adjusted to ensure the calculations 1004 * don't "wrap" when RSSI is less than the "adjusted" NF value. 1005 * ("Adjust" here is via ichan->noiseFloorAdjust.) 1006 */ 1007 for (i = 0; i < AH_MIMO_MAX_CHAINS; i++) { 1008 nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan); 1009 nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan); 1010 } 1011 return 1; 1012 } 1013 #else 1014 return 0; 1015 #endif /* AH_SUPPORT_AR5416 */ 1016 } 1017 1018 /* 1019 * Process all valid raw noise floors into the dBm noise floor values. 1020 * Though our device has no reference for a dBm noise floor, we perform 1021 * a relative minimization of NF's based on the lowest NF found across a 1022 * channel scan. 1023 */ 1024 void 1025 ath_hal_process_noisefloor(struct ath_hal *ah) 1026 { 1027 HAL_CHANNEL_INTERNAL *c; 1028 int16_t correct2, correct5; 1029 int16_t lowest2, lowest5; 1030 int i; 1031 1032 /* 1033 * Find the lowest 2GHz and 5GHz noise floor values after adjusting 1034 * for statistically recorded NF/channel deviation. 1035 */ 1036 correct2 = lowest2 = 0; 1037 correct5 = lowest5 = 0; 1038 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { 1039 WIRELESS_MODE mode; 1040 int16_t nf; 1041 1042 c = &AH_PRIVATE(ah)->ah_channels[i]; 1043 if (c->rawNoiseFloor >= 0) 1044 continue; 1045 /* XXX can't identify proper mode */ 1046 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g; 1047 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] + 1048 ath_hal_getNfAdjust(ah, c); 1049 if (IS_CHAN_5GHZ(c)) { 1050 if (nf < lowest5) { 1051 lowest5 = nf; 1052 correct5 = NOISE_FLOOR[mode] - 1053 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); 1054 } 1055 } else { 1056 if (nf < lowest2) { 1057 lowest2 = nf; 1058 correct2 = NOISE_FLOOR[mode] - 1059 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); 1060 } 1061 } 1062 } 1063 1064 /* Correct the channels to reach the expected NF value */ 1065 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { 1066 c = &AH_PRIVATE(ah)->ah_channels[i]; 1067 if (c->rawNoiseFloor >= 0) 1068 continue; 1069 /* Apply correction factor */ 1070 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) + 1071 (IS_CHAN_5GHZ(c) ? correct5 : correct2); 1072 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n", 1073 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust); 1074 } 1075 } 1076 1077 /* 1078 * INI support routines. 1079 */ 1080 1081 int 1082 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, 1083 int col, int regWr) 1084 { 1085 int r; 1086 1087 HALASSERT(col < ia->cols); 1088 for (r = 0; r < ia->rows; r++) { 1089 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), 1090 HAL_INI_VAL(ia, r, col)); 1091 1092 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */ 1093 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900) 1094 OS_DELAY(100); 1095 1096 DMA_YIELD(regWr); 1097 } 1098 return regWr; 1099 } 1100 1101 void 1102 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col) 1103 { 1104 int r; 1105 1106 HALASSERT(col < ia->cols); 1107 for (r = 0; r < ia->rows; r++) 1108 data[r] = HAL_INI_VAL(ia, r, col); 1109 } 1110 1111 int 1112 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, 1113 const uint32_t data[], int regWr) 1114 { 1115 int r; 1116 1117 for (r = 0; r < ia->rows; r++) { 1118 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]); 1119 DMA_YIELD(regWr); 1120 } 1121 return regWr; 1122 } 1123 1124 /* 1125 * These are EEPROM board related routines which should likely live in 1126 * a helper library of some sort. 1127 */ 1128 1129 /************************************************************** 1130 * ath_ee_getLowerUppderIndex 1131 * 1132 * Return indices surrounding the value in sorted integer lists. 1133 * Requirement: the input list must be monotonically increasing 1134 * and populated up to the list size 1135 * Returns: match is set if an index in the array matches exactly 1136 * or a the target is before or after the range of the array. 1137 */ 1138 HAL_BOOL 1139 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize, 1140 uint16_t *indexL, uint16_t *indexR) 1141 { 1142 uint16_t i; 1143 1144 /* 1145 * Check first and last elements for beyond ordered array cases. 1146 */ 1147 if (target <= pList[0]) { 1148 *indexL = *indexR = 0; 1149 return AH_TRUE; 1150 } 1151 if (target >= pList[listSize-1]) { 1152 *indexL = *indexR = (uint16_t)(listSize - 1); 1153 return AH_TRUE; 1154 } 1155 1156 /* look for value being near or between 2 values in list */ 1157 for (i = 0; i < listSize - 1; i++) { 1158 /* 1159 * If value is close to the current value of the list 1160 * then target is not between values, it is one of the values 1161 */ 1162 if (pList[i] == target) { 1163 *indexL = *indexR = i; 1164 return AH_TRUE; 1165 } 1166 /* 1167 * Look for value being between current value and next value 1168 * if so return these 2 values 1169 */ 1170 if (target < pList[i + 1]) { 1171 *indexL = i; 1172 *indexR = (uint16_t)(i + 1); 1173 return AH_FALSE; 1174 } 1175 } 1176 HALASSERT(0); 1177 *indexL = *indexR = 0; 1178 return AH_FALSE; 1179 } 1180 1181 /************************************************************** 1182 * ath_ee_FillVpdTable 1183 * 1184 * Fill the Vpdlist for indices Pmax-Pmin 1185 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4 1186 */ 1187 HAL_BOOL 1188 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, 1189 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList) 1190 { 1191 uint16_t i, k; 1192 uint8_t currPwr = pwrMin; 1193 uint16_t idxL, idxR; 1194 1195 HALASSERT(pwrMax > pwrMin); 1196 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { 1197 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts, 1198 &(idxL), &(idxR)); 1199 if (idxR < 1) 1200 idxR = 1; /* extrapolate below */ 1201 if (idxL == numIntercepts - 1) 1202 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */ 1203 if (pPwrList[idxL] == pPwrList[idxR]) 1204 k = pVpdList[idxL]; 1205 else 1206 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / 1207 (pPwrList[idxR] - pPwrList[idxL]) ); 1208 HALASSERT(k < 256); 1209 pRetVpdList[i] = (uint8_t)k; 1210 currPwr += 2; /* half dB steps */ 1211 } 1212 1213 return AH_TRUE; 1214 } 1215 1216 /************************************************************************** 1217 * ath_ee_interpolate 1218 * 1219 * Returns signed interpolated or the scaled up interpolated value 1220 */ 1221 int16_t 1222 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, 1223 int16_t targetLeft, int16_t targetRight) 1224 { 1225 int16_t rv; 1226 1227 if (srcRight == srcLeft) { 1228 rv = targetLeft; 1229 } else { 1230 rv = (int16_t)( ((target - srcLeft) * targetRight + 1231 (srcRight - target) * targetLeft) / (srcRight - srcLeft) ); 1232 } 1233 return rv; 1234 } 1235 1236 /* 1237 * Adjust the TSF. 1238 */ 1239 void 1240 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta) 1241 { 1242 /* XXX handle wrap/overflow */ 1243 OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta); 1244 } 1245 1246 /* 1247 * Enable or disable CCA. 1248 */ 1249 void 1250 ath_hal_setcca(struct ath_hal *ah, int ena) 1251 { 1252 /* 1253 * NB: fill me in; this is not provided by default because disabling 1254 * CCA in most locales violates regulatory. 1255 */ 1256 } 1257 1258 /* 1259 * Get CCA setting. 1260 */ 1261 int 1262 ath_hal_getcca(struct ath_hal *ah) 1263 { 1264 u_int32_t diag; 1265 if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK) 1266 return 1; 1267 return ((diag & 0x500000) == 0); 1268 } 1269