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