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) & 0xf) 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[rate & 0x1f]; 338 else 339 bitsPerSymbol = ht20_bps[rate & 0x1f]; 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 static WIRELESS_MODE 494 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan) 495 { 496 if (IEEE80211_IS_CHAN_B(chan)) 497 return WIRELESS_MODE_11b; 498 if (IEEE80211_IS_CHAN_G(chan)) 499 return WIRELESS_MODE_11g; 500 if (IEEE80211_IS_CHAN_108G(chan)) 501 return WIRELESS_MODE_108g; 502 if (IEEE80211_IS_CHAN_TURBO(chan)) 503 return WIRELESS_MODE_TURBO; 504 return WIRELESS_MODE_11a; 505 } 506 507 /* 508 * Convert between microseconds and core system clocks. 509 */ 510 /* 11a Turbo 11b 11g 108g */ 511 static const uint8_t CLOCK_RATE[] = { 40, 80, 22, 44, 88 }; 512 513 #define CLOCK_FAST_RATE_5GHZ_OFDM 44 514 515 u_int 516 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs) 517 { 518 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan; 519 u_int clks; 520 521 /* NB: ah_curchan may be null when called attach time */ 522 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */ 523 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) { 524 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM; 525 if (IEEE80211_IS_CHAN_HT40(c)) 526 clks <<= 1; 527 } else if (c != AH_NULL) { 528 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; 529 if (IEEE80211_IS_CHAN_HT40(c)) 530 clks <<= 1; 531 } else 532 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b]; 533 534 /* Compensate for half/quarter rate */ 535 if (c != AH_NULL && IEEE80211_IS_CHAN_HALF(c)) 536 clks = clks / 2; 537 else if (c != AH_NULL && IEEE80211_IS_CHAN_QUARTER(c)) 538 clks = clks / 4; 539 540 return clks; 541 } 542 543 u_int 544 ath_hal_mac_usec(struct ath_hal *ah, u_int clks) 545 { 546 const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan; 547 u_int usec; 548 549 /* NB: ah_curchan may be null when called attach time */ 550 /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */ 551 if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) { 552 usec = clks / CLOCK_FAST_RATE_5GHZ_OFDM; 553 if (IEEE80211_IS_CHAN_HT40(c)) 554 usec >>= 1; 555 } else if (c != AH_NULL) { 556 usec = clks / CLOCK_RATE[ath_hal_chan2wmode(ah, c)]; 557 if (IEEE80211_IS_CHAN_HT40(c)) 558 usec >>= 1; 559 } else 560 usec = clks / CLOCK_RATE[WIRELESS_MODE_11b]; 561 return usec; 562 } 563 564 /* 565 * Setup a h/w rate table's reverse lookup table and 566 * fill in ack durations. This routine is called for 567 * each rate table returned through the ah_getRateTable 568 * method. The reverse lookup tables are assumed to be 569 * initialized to zero (or at least the first entry). 570 * We use this as a key that indicates whether or not 571 * we've previously setup the reverse lookup table. 572 * 573 * XXX not reentrant, but shouldn't matter 574 */ 575 void 576 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt) 577 { 578 #define N(a) (sizeof(a)/sizeof(a[0])) 579 int i; 580 581 if (rt->rateCodeToIndex[0] != 0) /* already setup */ 582 return; 583 for (i = 0; i < N(rt->rateCodeToIndex); i++) 584 rt->rateCodeToIndex[i] = (uint8_t) -1; 585 for (i = 0; i < rt->rateCount; i++) { 586 uint8_t code = rt->info[i].rateCode; 587 uint8_t cix = rt->info[i].controlRate; 588 589 HALASSERT(code < N(rt->rateCodeToIndex)); 590 rt->rateCodeToIndex[code] = i; 591 HALASSERT((code | rt->info[i].shortPreamble) < 592 N(rt->rateCodeToIndex)); 593 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i; 594 /* 595 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s 596 * depends on whether they are marked as basic rates; 597 * the static tables are setup with an 11b-compatible 598 * 2Mb/s rate which will work but is suboptimal 599 */ 600 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt, 601 WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE, AH_TRUE); 602 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt, 603 WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE, AH_TRUE); 604 } 605 #undef N 606 } 607 608 HAL_STATUS 609 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 610 uint32_t capability, uint32_t *result) 611 { 612 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 613 614 switch (type) { 615 case HAL_CAP_REG_DMN: /* regulatory domain */ 616 *result = AH_PRIVATE(ah)->ah_currentRD; 617 return HAL_OK; 618 case HAL_CAP_DFS_DMN: /* DFS Domain */ 619 *result = AH_PRIVATE(ah)->ah_dfsDomain; 620 return HAL_OK; 621 case HAL_CAP_CIPHER: /* cipher handled in hardware */ 622 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ 623 return HAL_ENOTSUPP; 624 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ 625 return HAL_ENOTSUPP; 626 case HAL_CAP_PHYCOUNTERS: /* hardware PHY error counters */ 627 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO; 628 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC when WMM is turned on */ 629 return HAL_ENOTSUPP; 630 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ 631 return HAL_ENOTSUPP; 632 case HAL_CAP_KEYCACHE_SIZE: /* hardware key cache size */ 633 *result = pCap->halKeyCacheSize; 634 return HAL_OK; 635 case HAL_CAP_NUM_TXQUEUES: /* number of hardware tx queues */ 636 *result = pCap->halTotalQueues; 637 return HAL_OK; 638 case HAL_CAP_VEOL: /* hardware supports virtual EOL */ 639 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP; 640 case HAL_CAP_PSPOLL: /* hardware PS-Poll support works */ 641 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK; 642 case HAL_CAP_COMPRESSION: 643 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP; 644 case HAL_CAP_BURST: 645 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP; 646 case HAL_CAP_FASTFRAME: 647 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP; 648 case HAL_CAP_DIAG: /* hardware diagnostic support */ 649 *result = AH_PRIVATE(ah)->ah_diagreg; 650 return HAL_OK; 651 case HAL_CAP_TXPOW: /* global tx power limit */ 652 switch (capability) { 653 case 0: /* facility is supported */ 654 return HAL_OK; 655 case 1: /* current limit */ 656 *result = AH_PRIVATE(ah)->ah_powerLimit; 657 return HAL_OK; 658 case 2: /* current max tx power */ 659 *result = AH_PRIVATE(ah)->ah_maxPowerLevel; 660 return HAL_OK; 661 case 3: /* scale factor */ 662 *result = AH_PRIVATE(ah)->ah_tpScale; 663 return HAL_OK; 664 } 665 return HAL_ENOTSUPP; 666 case HAL_CAP_BSSIDMASK: /* hardware supports bssid mask */ 667 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP; 668 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ 669 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP; 670 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ 671 return HAL_ENOTSUPP; 672 case HAL_CAP_RFSILENT: /* rfsilent support */ 673 switch (capability) { 674 case 0: /* facility is supported */ 675 return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP; 676 case 1: /* current setting */ 677 return AH_PRIVATE(ah)->ah_rfkillEnabled ? 678 HAL_OK : HAL_ENOTSUPP; 679 case 2: /* rfsilent config */ 680 *result = AH_PRIVATE(ah)->ah_rfsilent; 681 return HAL_OK; 682 } 683 return HAL_ENOTSUPP; 684 case HAL_CAP_11D: 685 return HAL_OK; 686 687 case HAL_CAP_HT: 688 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP; 689 case HAL_CAP_GTXTO: 690 return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP; 691 case HAL_CAP_FAST_CC: 692 return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP; 693 case HAL_CAP_TX_CHAINMASK: /* mask of TX chains supported */ 694 *result = pCap->halTxChainMask; 695 return HAL_OK; 696 case HAL_CAP_RX_CHAINMASK: /* mask of RX chains supported */ 697 *result = pCap->halRxChainMask; 698 return HAL_OK; 699 case HAL_CAP_NUM_GPIO_PINS: 700 *result = pCap->halNumGpioPins; 701 return HAL_OK; 702 case HAL_CAP_CST: 703 return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP; 704 case HAL_CAP_RTS_AGGR_LIMIT: 705 *result = pCap->halRtsAggrLimit; 706 return HAL_OK; 707 case HAL_CAP_4ADDR_AGGR: 708 return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP; 709 case HAL_CAP_EXT_CHAN_DFS: 710 return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP; 711 case HAL_CAP_RX_STBC: 712 return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP; 713 case HAL_CAP_TX_STBC: 714 return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP; 715 case HAL_CAP_COMBINED_RADAR_RSSI: 716 return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP; 717 case HAL_CAP_AUTO_SLEEP: 718 return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP; 719 case HAL_CAP_MBSSID_AGGR_SUPPORT: 720 return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP; 721 case HAL_CAP_SPLIT_4KB_TRANS: /* hardware handles descriptors straddling 4k page boundary */ 722 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP; 723 case HAL_CAP_REG_FLAG: 724 *result = AH_PRIVATE(ah)->ah_currentRDext; 725 return HAL_OK; 726 case HAL_CAP_ENHANCED_DMA_SUPPORT: 727 return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP; 728 case HAL_CAP_NUM_TXMAPS: 729 *result = pCap->halNumTxMaps; 730 return HAL_OK; 731 case HAL_CAP_TXDESCLEN: 732 *result = pCap->halTxDescLen; 733 return HAL_OK; 734 case HAL_CAP_TXSTATUSLEN: 735 *result = pCap->halTxStatusLen; 736 return HAL_OK; 737 case HAL_CAP_RXSTATUSLEN: 738 *result = pCap->halRxStatusLen; 739 return HAL_OK; 740 case HAL_CAP_RXFIFODEPTH: 741 switch (capability) { 742 case HAL_RX_QUEUE_HP: 743 *result = pCap->halRxHpFifoDepth; 744 return HAL_OK; 745 case HAL_RX_QUEUE_LP: 746 *result = pCap->halRxLpFifoDepth; 747 return HAL_OK; 748 default: 749 return HAL_ENOTSUPP; 750 } 751 case HAL_CAP_RXBUFSIZE: 752 case HAL_CAP_NUM_MR_RETRIES: 753 *result = pCap->halNumMRRetries; 754 return HAL_OK; 755 case HAL_CAP_BT_COEX: 756 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP; 757 case HAL_CAP_SPECTRAL_SCAN: 758 return pCap->halSpectralScanSupport ? HAL_OK : HAL_ENOTSUPP; 759 case HAL_CAP_HT20_SGI: 760 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP; 761 case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */ 762 *result = pCap->halRxTstampPrecision; 763 return HAL_OK; 764 case HAL_CAP_ANT_DIV_COMB: /* AR9285/AR9485 LNA diversity */ 765 return pCap->halAntDivCombSupport ? HAL_OK : HAL_ENOTSUPP; 766 767 case HAL_CAP_ENHANCED_DFS_SUPPORT: 768 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP; 769 770 /* FreeBSD-specific entries for now */ 771 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ 772 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP; 773 case HAL_CAP_INTRMASK: /* mask of supported interrupts */ 774 *result = pCap->halIntrMask; 775 return HAL_OK; 776 case HAL_CAP_BSSIDMATCH: /* hardware has disable bssid match */ 777 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP; 778 case HAL_CAP_STREAMS: /* number of 11n spatial streams */ 779 switch (capability) { 780 case 0: /* TX */ 781 *result = pCap->halTxStreams; 782 return HAL_OK; 783 case 1: /* RX */ 784 *result = pCap->halRxStreams; 785 return HAL_OK; 786 default: 787 return HAL_ENOTSUPP; 788 } 789 case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */ 790 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP; 791 case HAL_CAP_BB_READ_WAR: /* Baseband read WAR */ 792 return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP; 793 case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */ 794 return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP; 795 case HAL_CAP_MFP: /* Management frame protection setting */ 796 *result = pCap->halMfpSupport; 797 return HAL_OK; 798 case HAL_CAP_RX_LNA_MIXING: /* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */ 799 return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP; 800 case HAL_CAP_DO_MYBEACON: /* Hardware supports filtering my-beacons */ 801 return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP; 802 case HAL_CAP_TXTSTAMP_PREC: /* tx desc tstamp precision (bits) */ 803 *result = pCap->halTxTstampPrecision; 804 return HAL_OK; 805 default: 806 return HAL_EINVAL; 807 } 808 } 809 810 HAL_BOOL 811 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 812 uint32_t capability, uint32_t setting, HAL_STATUS *status) 813 { 814 815 switch (type) { 816 case HAL_CAP_TXPOW: 817 switch (capability) { 818 case 3: 819 if (setting <= HAL_TP_SCALE_MIN) { 820 AH_PRIVATE(ah)->ah_tpScale = setting; 821 return AH_TRUE; 822 } 823 break; 824 } 825 break; 826 case HAL_CAP_RFSILENT: /* rfsilent support */ 827 /* 828 * NB: allow even if halRfSilentSupport is false 829 * in case the EEPROM is misprogrammed. 830 */ 831 switch (capability) { 832 case 1: /* current setting */ 833 AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0); 834 return AH_TRUE; 835 case 2: /* rfsilent config */ 836 /* XXX better done per-chip for validation? */ 837 AH_PRIVATE(ah)->ah_rfsilent = setting; 838 return AH_TRUE; 839 } 840 break; 841 case HAL_CAP_REG_DMN: /* regulatory domain */ 842 AH_PRIVATE(ah)->ah_currentRD = setting; 843 return AH_TRUE; 844 case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ 845 AH_PRIVATE(ah)->ah_rxornIsFatal = setting; 846 return AH_TRUE; 847 default: 848 break; 849 } 850 if (status) 851 *status = HAL_EINVAL; 852 return AH_FALSE; 853 } 854 855 /* 856 * Common support for getDiagState method. 857 */ 858 859 static u_int 860 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs, 861 void *dstbuf, int space) 862 { 863 uint32_t *dp = dstbuf; 864 int i; 865 866 for (i = 0; space >= 2*sizeof(uint32_t); i++) { 867 uint32_t r = regs[i].start; 868 uint32_t e = regs[i].end; 869 *dp++ = r; 870 *dp++ = e; 871 space -= 2*sizeof(uint32_t); 872 do { 873 *dp++ = OS_REG_READ(ah, r); 874 r += sizeof(uint32_t); 875 space -= sizeof(uint32_t); 876 } while (r <= e && space >= sizeof(uint32_t)); 877 } 878 return (char *) dp - (char *) dstbuf; 879 } 880 881 static void 882 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space) 883 { 884 while (space >= sizeof(HAL_REGWRITE)) { 885 OS_REG_WRITE(ah, regs->addr, regs->value); 886 regs++, space -= sizeof(HAL_REGWRITE); 887 } 888 } 889 890 HAL_BOOL 891 ath_hal_getdiagstate(struct ath_hal *ah, int request, 892 const void *args, uint32_t argsize, 893 void **result, uint32_t *resultsize) 894 { 895 896 switch (request) { 897 case HAL_DIAG_REVS: 898 *result = &AH_PRIVATE(ah)->ah_devid; 899 *resultsize = sizeof(HAL_REVS); 900 return AH_TRUE; 901 case HAL_DIAG_REGS: 902 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize); 903 return AH_TRUE; 904 case HAL_DIAG_SETREGS: 905 ath_hal_setregs(ah, args, argsize); 906 *resultsize = 0; 907 return AH_TRUE; 908 case HAL_DIAG_FATALERR: 909 *result = &AH_PRIVATE(ah)->ah_fatalState[0]; 910 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState); 911 return AH_TRUE; 912 case HAL_DIAG_EEREAD: 913 if (argsize != sizeof(uint16_t)) 914 return AH_FALSE; 915 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result)) 916 return AH_FALSE; 917 *resultsize = sizeof(uint16_t); 918 return AH_TRUE; 919 #ifdef AH_PRIVATE_DIAG 920 case HAL_DIAG_SETKEY: { 921 const HAL_DIAG_KEYVAL *dk; 922 923 if (argsize != sizeof(HAL_DIAG_KEYVAL)) 924 return AH_FALSE; 925 dk = (const HAL_DIAG_KEYVAL *)args; 926 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix, 927 &dk->dk_keyval, dk->dk_mac, dk->dk_xor); 928 } 929 case HAL_DIAG_RESETKEY: 930 if (argsize != sizeof(uint16_t)) 931 return AH_FALSE; 932 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args); 933 #ifdef AH_SUPPORT_WRITE_EEPROM 934 case HAL_DIAG_EEWRITE: { 935 const HAL_DIAG_EEVAL *ee; 936 if (argsize != sizeof(HAL_DIAG_EEVAL)) 937 return AH_FALSE; 938 ee = (const HAL_DIAG_EEVAL *)args; 939 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data); 940 } 941 #endif /* AH_SUPPORT_WRITE_EEPROM */ 942 #endif /* AH_PRIVATE_DIAG */ 943 case HAL_DIAG_11NCOMPAT: 944 if (argsize == 0) { 945 *resultsize = sizeof(uint32_t); 946 *((uint32_t *)(*result)) = 947 AH_PRIVATE(ah)->ah_11nCompat; 948 } else if (argsize == sizeof(uint32_t)) { 949 AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args; 950 } else 951 return AH_FALSE; 952 return AH_TRUE; 953 case HAL_DIAG_CHANSURVEY: 954 *result = &AH_PRIVATE(ah)->ah_chansurvey; 955 *resultsize = sizeof(HAL_CHANNEL_SURVEY); 956 return AH_TRUE; 957 } 958 return AH_FALSE; 959 } 960 961 /* 962 * Set the properties of the tx queue with the parameters 963 * from qInfo. 964 */ 965 HAL_BOOL 966 ath_hal_setTxQProps(struct ath_hal *ah, 967 HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo) 968 { 969 uint32_t cw; 970 971 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 972 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, 973 "%s: inactive queue\n", __func__); 974 return AH_FALSE; 975 } 976 /* XXX validate parameters */ 977 qi->tqi_ver = qInfo->tqi_ver; 978 qi->tqi_subtype = qInfo->tqi_subtype; 979 qi->tqi_qflags = qInfo->tqi_qflags; 980 qi->tqi_priority = qInfo->tqi_priority; 981 if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT) 982 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255); 983 else 984 qi->tqi_aifs = INIT_AIFS; 985 if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) { 986 cw = AH_MIN(qInfo->tqi_cwmin, 1024); 987 /* make sure that the CWmin is of the form (2^n - 1) */ 988 qi->tqi_cwmin = 1; 989 while (qi->tqi_cwmin < cw) 990 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; 991 } else 992 qi->tqi_cwmin = qInfo->tqi_cwmin; 993 if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) { 994 cw = AH_MIN(qInfo->tqi_cwmax, 1024); 995 /* make sure that the CWmax is of the form (2^n - 1) */ 996 qi->tqi_cwmax = 1; 997 while (qi->tqi_cwmax < cw) 998 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; 999 } else 1000 qi->tqi_cwmax = INIT_CWMAX; 1001 /* Set retry limit values */ 1002 if (qInfo->tqi_shretry != 0) 1003 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15); 1004 else 1005 qi->tqi_shretry = INIT_SH_RETRY; 1006 if (qInfo->tqi_lgretry != 0) 1007 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15); 1008 else 1009 qi->tqi_lgretry = INIT_LG_RETRY; 1010 qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod; 1011 qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit; 1012 qi->tqi_burstTime = qInfo->tqi_burstTime; 1013 qi->tqi_readyTime = qInfo->tqi_readyTime; 1014 1015 switch (qInfo->tqi_subtype) { 1016 case HAL_WME_UPSD: 1017 if (qi->tqi_type == HAL_TX_QUEUE_DATA) 1018 qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS; 1019 break; 1020 default: 1021 break; /* NB: silence compiler */ 1022 } 1023 return AH_TRUE; 1024 } 1025 1026 HAL_BOOL 1027 ath_hal_getTxQProps(struct ath_hal *ah, 1028 HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi) 1029 { 1030 if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 1031 HALDEBUG(ah, HAL_DEBUG_TXQUEUE, 1032 "%s: inactive queue\n", __func__); 1033 return AH_FALSE; 1034 } 1035 1036 qInfo->tqi_qflags = qi->tqi_qflags; 1037 qInfo->tqi_ver = qi->tqi_ver; 1038 qInfo->tqi_subtype = qi->tqi_subtype; 1039 qInfo->tqi_qflags = qi->tqi_qflags; 1040 qInfo->tqi_priority = qi->tqi_priority; 1041 qInfo->tqi_aifs = qi->tqi_aifs; 1042 qInfo->tqi_cwmin = qi->tqi_cwmin; 1043 qInfo->tqi_cwmax = qi->tqi_cwmax; 1044 qInfo->tqi_shretry = qi->tqi_shretry; 1045 qInfo->tqi_lgretry = qi->tqi_lgretry; 1046 qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; 1047 qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; 1048 qInfo->tqi_burstTime = qi->tqi_burstTime; 1049 qInfo->tqi_readyTime = qi->tqi_readyTime; 1050 return AH_TRUE; 1051 } 1052 1053 /* 11a Turbo 11b 11g 108g */ 1054 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93 }; 1055 1056 /* 1057 * Read the current channel noise floor and return. 1058 * If nf cal hasn't finished, channel noise floor should be 0 1059 * and we return a nominal value based on band and frequency. 1060 * 1061 * NB: This is a private routine used by per-chip code to 1062 * implement the ah_getChanNoise method. 1063 */ 1064 int16_t 1065 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan) 1066 { 1067 HAL_CHANNEL_INTERNAL *ichan; 1068 1069 ichan = ath_hal_checkchannel(ah, chan); 1070 if (ichan == AH_NULL) { 1071 HALDEBUG(ah, HAL_DEBUG_NFCAL, 1072 "%s: invalid channel %u/0x%x; no mapping\n", 1073 __func__, chan->ic_freq, chan->ic_flags); 1074 return 0; 1075 } 1076 if (ichan->rawNoiseFloor == 0) { 1077 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); 1078 1079 HALASSERT(mode < WIRELESS_MODE_MAX); 1080 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan); 1081 } else 1082 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust; 1083 } 1084 1085 /* 1086 * Fetch the current setup of ctl/ext noise floor values. 1087 * 1088 * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply 1089 * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust(). 1090 * 1091 * The caller must supply ctl/ext NF arrays which are at least 1092 * AH_MAX_CHAINS entries long. 1093 */ 1094 int 1095 ath_hal_get_mimo_chan_noise(struct ath_hal *ah, 1096 const struct ieee80211_channel *chan, int16_t *nf_ctl, 1097 int16_t *nf_ext) 1098 { 1099 #ifdef AH_SUPPORT_AR5416 1100 HAL_CHANNEL_INTERNAL *ichan; 1101 int i; 1102 1103 ichan = ath_hal_checkchannel(ah, chan); 1104 if (ichan == AH_NULL) { 1105 HALDEBUG(ah, HAL_DEBUG_NFCAL, 1106 "%s: invalid channel %u/0x%x; no mapping\n", 1107 __func__, chan->ic_freq, chan->ic_flags); 1108 for (i = 0; i < AH_MAX_CHAINS; i++) { 1109 nf_ctl[i] = nf_ext[i] = 0; 1110 } 1111 return 0; 1112 } 1113 1114 /* Return 0 if there's no valid MIMO values (yet) */ 1115 if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) { 1116 for (i = 0; i < AH_MAX_CHAINS; i++) { 1117 nf_ctl[i] = nf_ext[i] = 0; 1118 } 1119 return 0; 1120 } 1121 if (ichan->rawNoiseFloor == 0) { 1122 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan); 1123 HALASSERT(mode < WIRELESS_MODE_MAX); 1124 /* 1125 * See the comment below - this could cause issues for 1126 * stations which have a very low RSSI, below the 1127 * 'normalised' NF values in NOISE_FLOOR[]. 1128 */ 1129 for (i = 0; i < AH_MAX_CHAINS; i++) { 1130 nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] + 1131 ath_hal_getNfAdjust(ah, ichan); 1132 } 1133 return 1; 1134 } else { 1135 /* 1136 * The value returned here from a MIMO radio is presumed to be 1137 * "good enough" as a NF calculation. As RSSI values are calculated 1138 * against this, an adjusted NF may be higher than the RSSI value 1139 * returned from a vary weak station, resulting in an obscenely 1140 * high signal strength calculation being returned. 1141 * 1142 * This should be re-evaluated at a later date, along with any 1143 * signal strength calculations which are made. Quite likely the 1144 * RSSI values will need to be adjusted to ensure the calculations 1145 * don't "wrap" when RSSI is less than the "adjusted" NF value. 1146 * ("Adjust" here is via ichan->noiseFloorAdjust.) 1147 */ 1148 for (i = 0; i < AH_MAX_CHAINS; i++) { 1149 nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan); 1150 nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan); 1151 } 1152 return 1; 1153 } 1154 #else 1155 return 0; 1156 #endif /* AH_SUPPORT_AR5416 */ 1157 } 1158 1159 /* 1160 * Process all valid raw noise floors into the dBm noise floor values. 1161 * Though our device has no reference for a dBm noise floor, we perform 1162 * a relative minimization of NF's based on the lowest NF found across a 1163 * channel scan. 1164 */ 1165 void 1166 ath_hal_process_noisefloor(struct ath_hal *ah) 1167 { 1168 HAL_CHANNEL_INTERNAL *c; 1169 int16_t correct2, correct5; 1170 int16_t lowest2, lowest5; 1171 int i; 1172 1173 /* 1174 * Find the lowest 2GHz and 5GHz noise floor values after adjusting 1175 * for statistically recorded NF/channel deviation. 1176 */ 1177 correct2 = lowest2 = 0; 1178 correct5 = lowest5 = 0; 1179 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { 1180 WIRELESS_MODE mode; 1181 int16_t nf; 1182 1183 c = &AH_PRIVATE(ah)->ah_channels[i]; 1184 if (c->rawNoiseFloor >= 0) 1185 continue; 1186 /* XXX can't identify proper mode */ 1187 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g; 1188 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] + 1189 ath_hal_getNfAdjust(ah, c); 1190 if (IS_CHAN_5GHZ(c)) { 1191 if (nf < lowest5) { 1192 lowest5 = nf; 1193 correct5 = NOISE_FLOOR[mode] - 1194 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); 1195 } 1196 } else { 1197 if (nf < lowest2) { 1198 lowest2 = nf; 1199 correct2 = NOISE_FLOOR[mode] - 1200 (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c)); 1201 } 1202 } 1203 } 1204 1205 /* Correct the channels to reach the expected NF value */ 1206 for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) { 1207 c = &AH_PRIVATE(ah)->ah_channels[i]; 1208 if (c->rawNoiseFloor >= 0) 1209 continue; 1210 /* Apply correction factor */ 1211 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) + 1212 (IS_CHAN_5GHZ(c) ? correct5 : correct2); 1213 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n", 1214 c->channel, c->rawNoiseFloor, c->noiseFloorAdjust); 1215 } 1216 } 1217 1218 /* 1219 * INI support routines. 1220 */ 1221 1222 int 1223 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, 1224 int col, int regWr) 1225 { 1226 int r; 1227 1228 HALASSERT(col < ia->cols); 1229 for (r = 0; r < ia->rows; r++) { 1230 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), 1231 HAL_INI_VAL(ia, r, col)); 1232 1233 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */ 1234 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900) 1235 OS_DELAY(100); 1236 1237 DMA_YIELD(regWr); 1238 } 1239 return regWr; 1240 } 1241 1242 void 1243 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col) 1244 { 1245 int r; 1246 1247 HALASSERT(col < ia->cols); 1248 for (r = 0; r < ia->rows; r++) 1249 data[r] = HAL_INI_VAL(ia, r, col); 1250 } 1251 1252 int 1253 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia, 1254 const uint32_t data[], int regWr) 1255 { 1256 int r; 1257 1258 for (r = 0; r < ia->rows; r++) { 1259 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]); 1260 DMA_YIELD(regWr); 1261 } 1262 return regWr; 1263 } 1264 1265 /* 1266 * These are EEPROM board related routines which should likely live in 1267 * a helper library of some sort. 1268 */ 1269 1270 /************************************************************** 1271 * ath_ee_getLowerUppderIndex 1272 * 1273 * Return indices surrounding the value in sorted integer lists. 1274 * Requirement: the input list must be monotonically increasing 1275 * and populated up to the list size 1276 * Returns: match is set if an index in the array matches exactly 1277 * or a the target is before or after the range of the array. 1278 */ 1279 HAL_BOOL 1280 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize, 1281 uint16_t *indexL, uint16_t *indexR) 1282 { 1283 uint16_t i; 1284 1285 /* 1286 * Check first and last elements for beyond ordered array cases. 1287 */ 1288 if (target <= pList[0]) { 1289 *indexL = *indexR = 0; 1290 return AH_TRUE; 1291 } 1292 if (target >= pList[listSize-1]) { 1293 *indexL = *indexR = (uint16_t)(listSize - 1); 1294 return AH_TRUE; 1295 } 1296 1297 /* look for value being near or between 2 values in list */ 1298 for (i = 0; i < listSize - 1; i++) { 1299 /* 1300 * If value is close to the current value of the list 1301 * then target is not between values, it is one of the values 1302 */ 1303 if (pList[i] == target) { 1304 *indexL = *indexR = i; 1305 return AH_TRUE; 1306 } 1307 /* 1308 * Look for value being between current value and next value 1309 * if so return these 2 values 1310 */ 1311 if (target < pList[i + 1]) { 1312 *indexL = i; 1313 *indexR = (uint16_t)(i + 1); 1314 return AH_FALSE; 1315 } 1316 } 1317 HALASSERT(0); 1318 *indexL = *indexR = 0; 1319 return AH_FALSE; 1320 } 1321 1322 /************************************************************** 1323 * ath_ee_FillVpdTable 1324 * 1325 * Fill the Vpdlist for indices Pmax-Pmin 1326 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4 1327 */ 1328 HAL_BOOL 1329 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, 1330 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList) 1331 { 1332 uint16_t i, k; 1333 uint8_t currPwr = pwrMin; 1334 uint16_t idxL, idxR; 1335 1336 HALASSERT(pwrMax > pwrMin); 1337 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { 1338 ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts, 1339 &(idxL), &(idxR)); 1340 if (idxR < 1) 1341 idxR = 1; /* extrapolate below */ 1342 if (idxL == numIntercepts - 1) 1343 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */ 1344 if (pPwrList[idxL] == pPwrList[idxR]) 1345 k = pVpdList[idxL]; 1346 else 1347 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / 1348 (pPwrList[idxR] - pPwrList[idxL]) ); 1349 HALASSERT(k < 256); 1350 pRetVpdList[i] = (uint8_t)k; 1351 currPwr += 2; /* half dB steps */ 1352 } 1353 1354 return AH_TRUE; 1355 } 1356 1357 /************************************************************************** 1358 * ath_ee_interpolate 1359 * 1360 * Returns signed interpolated or the scaled up interpolated value 1361 */ 1362 int16_t 1363 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, 1364 int16_t targetLeft, int16_t targetRight) 1365 { 1366 int16_t rv; 1367 1368 if (srcRight == srcLeft) { 1369 rv = targetLeft; 1370 } else { 1371 rv = (int16_t)( ((target - srcLeft) * targetRight + 1372 (srcRight - target) * targetLeft) / (srcRight - srcLeft) ); 1373 } 1374 return rv; 1375 } 1376 1377 /* 1378 * Adjust the TSF. 1379 */ 1380 void 1381 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta) 1382 { 1383 /* XXX handle wrap/overflow */ 1384 OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta); 1385 } 1386 1387 /* 1388 * Enable or disable CCA. 1389 */ 1390 void 1391 ath_hal_setcca(struct ath_hal *ah, int ena) 1392 { 1393 /* 1394 * NB: fill me in; this is not provided by default because disabling 1395 * CCA in most locales violates regulatory. 1396 */ 1397 } 1398 1399 /* 1400 * Get CCA setting. 1401 */ 1402 int 1403 ath_hal_getcca(struct ath_hal *ah) 1404 { 1405 u_int32_t diag; 1406 if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK) 1407 return 1; 1408 return ((diag & 0x500000) == 0); 1409 } 1410 1411 /* 1412 * This routine is only needed when supporting EEPROM-in-RAM setups 1413 * (eg embedded SoCs and on-board PCI/PCIe devices.) 1414 */ 1415 /* NB: This is in 16 bit words; not bytes */ 1416 /* XXX This doesn't belong here! */ 1417 #define ATH_DATA_EEPROM_SIZE 2048 1418 1419 HAL_BOOL 1420 ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data) 1421 { 1422 if (ah->ah_eepromdata == AH_NULL) { 1423 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__); 1424 return AH_FALSE; 1425 } 1426 if (off > ATH_DATA_EEPROM_SIZE) { 1427 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n", 1428 __func__, off, ATH_DATA_EEPROM_SIZE); 1429 return AH_FALSE; 1430 } 1431 (*data) = ah->ah_eepromdata[off]; 1432 return AH_TRUE; 1433 } 1434 1435 /* 1436 * Do a 2GHz specific MHz->IEEE based on the hardware 1437 * frequency. 1438 * 1439 * This is the unmapped frequency which is programmed into the hardware. 1440 */ 1441 int 1442 ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, int freq) 1443 { 1444 1445 if (freq == 2484) 1446 return 14; 1447 if (freq < 2484) 1448 return ((int) freq - 2407) / 5; 1449 else 1450 return 15 + ((freq - 2512) / 20); 1451 } 1452 1453 /* 1454 * Clear the current survey data. 1455 * 1456 * This should be done during a channel change. 1457 */ 1458 void 1459 ath_hal_survey_clear(struct ath_hal *ah) 1460 { 1461 1462 OS_MEMZERO(&AH_PRIVATE(ah)->ah_chansurvey, 1463 sizeof(AH_PRIVATE(ah)->ah_chansurvey)); 1464 } 1465 1466 /* 1467 * Add a sample to the channel survey. 1468 */ 1469 void 1470 ath_hal_survey_add_sample(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs) 1471 { 1472 HAL_CHANNEL_SURVEY *cs; 1473 1474 cs = &AH_PRIVATE(ah)->ah_chansurvey; 1475 1476 OS_MEMCPY(&cs->samples[cs->cur_sample], hs, sizeof(*hs)); 1477 cs->samples[cs->cur_sample].seq_num = cs->cur_seq; 1478 cs->cur_sample = (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT; 1479 cs->cur_seq++; 1480 } 1481