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_desc.h" /* NB: for HAL_PHYERR* */ 25 26 #include "ar5212/ar5212.h" 27 #include "ar5212/ar5212reg.h" 28 #include "ar5212/ar5212phy.h" 29 30 #include "ah_eeprom_v3.h" 31 32 #define AR_NUM_GPIO 6 /* 6 GPIO pins */ 33 #define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ 34 35 void 36 ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac) 37 { 38 struct ath_hal_5212 *ahp = AH5212(ah); 39 40 OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); 41 } 42 43 HAL_BOOL 44 ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac) 45 { 46 struct ath_hal_5212 *ahp = AH5212(ah); 47 48 OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); 49 return AH_TRUE; 50 } 51 52 void 53 ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask) 54 { 55 struct ath_hal_5212 *ahp = AH5212(ah); 56 57 OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN); 58 } 59 60 HAL_BOOL 61 ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) 62 { 63 struct ath_hal_5212 *ahp = AH5212(ah); 64 65 /* save it since it must be rewritten on reset */ 66 OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN); 67 68 OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); 69 OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); 70 return AH_TRUE; 71 } 72 73 /* 74 * Attempt to change the cards operating regulatory domain to the given value 75 */ 76 HAL_BOOL 77 ar5212SetRegulatoryDomain(struct ath_hal *ah, 78 uint16_t regDomain, HAL_STATUS *status) 79 { 80 HAL_STATUS ecode; 81 82 if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { 83 ecode = HAL_EINVAL; 84 goto bad; 85 } 86 if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { 87 ecode = HAL_EEWRITE; 88 goto bad; 89 } 90 #ifdef AH_SUPPORT_WRITE_REGDOMAIN 91 if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { 92 HALDEBUG(ah, HAL_DEBUG_ANY, 93 "%s: set regulatory domain to %u (0x%x)\n", 94 __func__, regDomain, regDomain); 95 AH_PRIVATE(ah)->ah_currentRD = regDomain; 96 return AH_TRUE; 97 } 98 #endif 99 ecode = HAL_EIO; 100 bad: 101 if (status) 102 *status = ecode; 103 return AH_FALSE; 104 } 105 106 /* 107 * Return the wireless modes (a,b,g,t) supported by hardware. 108 * 109 * This value is what is actually supported by the hardware 110 * and is unaffected by regulatory/country code settings. 111 */ 112 u_int 113 ar5212GetWirelessModes(struct ath_hal *ah) 114 { 115 u_int mode = 0; 116 117 if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { 118 mode = HAL_MODE_11A; 119 if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) 120 mode |= HAL_MODE_TURBO | HAL_MODE_108A; 121 if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) 122 mode |= HAL_MODE_11A_HALF_RATE; 123 if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) 124 mode |= HAL_MODE_11A_QUARTER_RATE; 125 } 126 if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) 127 mode |= HAL_MODE_11B; 128 if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) && 129 AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { 130 mode |= HAL_MODE_11G; 131 if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) 132 mode |= HAL_MODE_108G; 133 if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) 134 mode |= HAL_MODE_11G_HALF_RATE; 135 if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) 136 mode |= HAL_MODE_11G_QUARTER_RATE; 137 } 138 return mode; 139 } 140 141 /* 142 * Set the interrupt and GPIO values so the ISR can disable RF 143 * on a switch signal. Assumes GPIO port and interrupt polarity 144 * are set prior to call. 145 */ 146 void 147 ar5212EnableRfKill(struct ath_hal *ah) 148 { 149 uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; 150 int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); 151 int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); 152 153 /* 154 * Configure the desired GPIO port for input 155 * and enable baseband rf silence. 156 */ 157 ath_hal_gpioCfgInput(ah, select); 158 OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000); 159 /* 160 * If radio disable switch connection to GPIO bit x is enabled 161 * program GPIO interrupt. 162 * If rfkill bit on eeprom is 1, setupeeprommap routine has already 163 * verified that it is a later version of eeprom, it has a place for 164 * rfkill bit and it is set to 1, indicating that GPIO bit x hardware 165 * connection is present. 166 */ 167 ath_hal_gpioSetIntr(ah, select, 168 (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity)); 169 } 170 171 /* 172 * Change the LED blinking pattern to correspond to the connectivity 173 */ 174 void 175 ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state) 176 { 177 static const uint32_t ledbits[8] = { 178 AR_PCICFG_LEDCTL_NONE, /* HAL_LED_INIT */ 179 AR_PCICFG_LEDCTL_PEND, /* HAL_LED_SCAN */ 180 AR_PCICFG_LEDCTL_PEND, /* HAL_LED_AUTH */ 181 AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/ 182 AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */ 183 AR_PCICFG_LEDCTL_NONE, 184 AR_PCICFG_LEDCTL_NONE, 185 AR_PCICFG_LEDCTL_NONE, 186 }; 187 uint32_t bits; 188 189 bits = OS_REG_READ(ah, AR_PCICFG); 190 if (IS_2417(ah)) { 191 /* 192 * Enable LED for Nala. There is a bit marked reserved 193 * that must be set and we also turn on the power led. 194 * Because we mark s/w LED control setting the control 195 * status bits below is meangless (the driver must flash 196 * the LED(s) using the GPIO lines). 197 */ 198 bits = (bits &~ AR_PCICFG_LEDMODE) 199 | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE) 200 #if 0 201 | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE) 202 #endif 203 | 0x08000000; 204 } 205 bits = (bits &~ AR_PCICFG_LEDCTL) 206 | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL); 207 OS_REG_WRITE(ah, AR_PCICFG, bits); 208 } 209 210 /* 211 * Change association related fields programmed into the hardware. 212 * Writing a valid BSSID to the hardware effectively enables the hardware 213 * to synchronize its TSF to the correct beacons and receive frames coming 214 * from that BSSID. It is called by the SME JOIN operation. 215 */ 216 void 217 ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) 218 { 219 struct ath_hal_5212 *ahp = AH5212(ah); 220 221 /* save bssid for possible re-use on reset */ 222 OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); 223 ahp->ah_assocId = assocId; 224 OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); 225 OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | 226 ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S)); 227 } 228 229 /* 230 * Get the current hardware tsf for stamlme 231 */ 232 uint64_t 233 ar5212GetTsf64(struct ath_hal *ah) 234 { 235 uint32_t low1, low2, u32; 236 237 /* sync multi-word read */ 238 low1 = OS_REG_READ(ah, AR_TSF_L32); 239 u32 = OS_REG_READ(ah, AR_TSF_U32); 240 low2 = OS_REG_READ(ah, AR_TSF_L32); 241 if (low2 < low1) { /* roll over */ 242 /* 243 * If we are not preempted this will work. If we are 244 * then we re-reading AR_TSF_U32 does no good as the 245 * low bits will be meaningless. Likewise reading 246 * L32, U32, U32, then comparing the last two reads 247 * to check for rollover doesn't help if preempted--so 248 * we take this approach as it costs one less PCI read 249 * which can be noticeable when doing things like 250 * timestamping packets in monitor mode. 251 */ 252 u32++; 253 } 254 return (((uint64_t) u32) << 32) | ((uint64_t) low2); 255 } 256 257 /* 258 * Get the current hardware tsf for stamlme 259 */ 260 uint32_t 261 ar5212GetTsf32(struct ath_hal *ah) 262 { 263 return OS_REG_READ(ah, AR_TSF_L32); 264 } 265 266 void 267 ar5212SetTsf64(struct ath_hal *ah, uint64_t tsf64) 268 { 269 OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); 270 OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); 271 } 272 273 /* 274 * Reset the current hardware tsf for stamlme. 275 */ 276 void 277 ar5212ResetTsf(struct ath_hal *ah) 278 { 279 280 uint32_t val = OS_REG_READ(ah, AR_BEACON); 281 282 OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); 283 /* 284 * When resetting the TSF, write twice to the 285 * corresponding register; each write to the RESET_TSF bit toggles 286 * the internal signal to cause a reset of the TSF - but if the signal 287 * is left high, it will reset the TSF on the next chip reset also! 288 * writing the bit an even number of times fixes this issue 289 */ 290 OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); 291 } 292 293 /* 294 * Set or clear hardware basic rate bit 295 * Set hardware basic rate set if basic rate is found 296 * and basic rate is equal or less than 2Mbps 297 */ 298 void 299 ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs) 300 { 301 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 302 uint32_t reg; 303 uint8_t xset; 304 int i; 305 306 if (chan == AH_NULL || !IEEE80211_IS_CHAN_CCK(chan)) 307 return; 308 xset = 0; 309 for (i = 0; i < rs->rs_count; i++) { 310 uint8_t rset = rs->rs_rates[i]; 311 /* Basic rate defined? */ 312 if ((rset & 0x80) && (rset &= 0x7f) >= xset) 313 xset = rset; 314 } 315 /* 316 * Set the h/w bit to reflect whether or not the basic 317 * rate is found to be equal or less than 2Mbps. 318 */ 319 reg = OS_REG_READ(ah, AR_STA_ID1); 320 if (xset && xset/2 <= 2) 321 OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B); 322 else 323 OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B); 324 } 325 326 /* 327 * Grab a semi-random value from hardware registers - may not 328 * change often 329 */ 330 uint32_t 331 ar5212GetRandomSeed(struct ath_hal *ah) 332 { 333 uint32_t nf; 334 335 nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; 336 if (nf & 0x100) 337 nf = 0 - ((nf ^ 0x1ff) + 1); 338 return (OS_REG_READ(ah, AR_TSF_U32) ^ 339 OS_REG_READ(ah, AR_TSF_L32) ^ nf); 340 } 341 342 /* 343 * Detect if our card is present 344 */ 345 HAL_BOOL 346 ar5212DetectCardPresent(struct ath_hal *ah) 347 { 348 uint16_t macVersion, macRev; 349 uint32_t v; 350 351 /* 352 * Read the Silicon Revision register and compare that 353 * to what we read at attach time. If the same, we say 354 * a card/device is present. 355 */ 356 v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; 357 macVersion = v >> AR_SREV_ID_S; 358 macRev = v & AR_SREV_REVISION; 359 return (AH_PRIVATE(ah)->ah_macVersion == macVersion && 360 AH_PRIVATE(ah)->ah_macRev == macRev); 361 } 362 363 void 364 ar5212EnableMibCounters(struct ath_hal *ah) 365 { 366 /* NB: this just resets the mib counter machinery */ 367 OS_REG_WRITE(ah, AR_MIBC, 368 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f); 369 } 370 371 void 372 ar5212DisableMibCounters(struct ath_hal *ah) 373 { 374 OS_REG_WRITE(ah, AR_MIBC, AR_MIBC | AR_MIBC_CMC); 375 } 376 377 /* 378 * Update MIB Counters 379 */ 380 void 381 ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats) 382 { 383 stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); 384 stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); 385 stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); 386 stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); 387 stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); 388 } 389 390 /* 391 * Detect if the HW supports spreading a CCK signal on channel 14 392 */ 393 HAL_BOOL 394 ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah) 395 { 396 return AH_TRUE; 397 } 398 399 /* 400 * Get the rssi of frame curently being received. 401 */ 402 uint32_t 403 ar5212GetCurRssi(struct ath_hal *ah) 404 { 405 return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); 406 } 407 408 u_int 409 ar5212GetDefAntenna(struct ath_hal *ah) 410 { 411 return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); 412 } 413 414 void 415 ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna) 416 { 417 OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); 418 } 419 420 HAL_ANT_SETTING 421 ar5212GetAntennaSwitch(struct ath_hal *ah) 422 { 423 return AH5212(ah)->ah_antControl; 424 } 425 426 HAL_BOOL 427 ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting) 428 { 429 struct ath_hal_5212 *ahp = AH5212(ah); 430 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 431 432 if (!ahp->ah_phyPowerOn || chan == AH_NULL) { 433 /* PHY powered off, just stash settings */ 434 ahp->ah_antControl = setting; 435 ahp->ah_diversity = (setting == HAL_ANT_VARIABLE); 436 return AH_TRUE; 437 } 438 return ar5212SetAntennaSwitchInternal(ah, setting, chan); 439 } 440 441 HAL_BOOL 442 ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah) 443 { 444 return AH_TRUE; 445 } 446 447 HAL_BOOL 448 ar5212SetSifsTime(struct ath_hal *ah, u_int us) 449 { 450 struct ath_hal_5212 *ahp = AH5212(ah); 451 452 if (us > ath_hal_mac_usec(ah, 0xffff)) { 453 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", 454 __func__, us); 455 ahp->ah_sifstime = (u_int) -1; /* restore default handling */ 456 return AH_FALSE; 457 } else { 458 /* convert to system clocks */ 459 OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2)); 460 ahp->ah_sifstime = us; 461 return AH_TRUE; 462 } 463 } 464 465 u_int 466 ar5212GetSifsTime(struct ath_hal *ah) 467 { 468 u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; 469 return ath_hal_mac_usec(ah, clks)+2; /* convert from system clocks */ 470 } 471 472 HAL_BOOL 473 ar5212SetSlotTime(struct ath_hal *ah, u_int us) 474 { 475 struct ath_hal_5212 *ahp = AH5212(ah); 476 477 if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) { 478 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", 479 __func__, us); 480 ahp->ah_slottime = (u_int) -1; /* restore default handling */ 481 return AH_FALSE; 482 } else { 483 /* convert to system clocks */ 484 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); 485 ahp->ah_slottime = us; 486 return AH_TRUE; 487 } 488 } 489 490 u_int 491 ar5212GetSlotTime(struct ath_hal *ah) 492 { 493 u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; 494 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 495 } 496 497 HAL_BOOL 498 ar5212SetAckTimeout(struct ath_hal *ah, u_int us) 499 { 500 struct ath_hal_5212 *ahp = AH5212(ah); 501 502 if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { 503 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", 504 __func__, us); 505 ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ 506 return AH_FALSE; 507 } else { 508 /* convert to system clocks */ 509 OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 510 AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); 511 ahp->ah_acktimeout = us; 512 return AH_TRUE; 513 } 514 } 515 516 u_int 517 ar5212GetAckTimeout(struct ath_hal *ah) 518 { 519 u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); 520 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 521 } 522 523 u_int 524 ar5212GetAckCTSRate(struct ath_hal *ah) 525 { 526 return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); 527 } 528 529 HAL_BOOL 530 ar5212SetAckCTSRate(struct ath_hal *ah, u_int high) 531 { 532 struct ath_hal_5212 *ahp = AH5212(ah); 533 534 if (high) { 535 OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 536 ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; 537 } else { 538 OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 539 ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; 540 } 541 return AH_TRUE; 542 } 543 544 HAL_BOOL 545 ar5212SetCTSTimeout(struct ath_hal *ah, u_int us) 546 { 547 struct ath_hal_5212 *ahp = AH5212(ah); 548 549 if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { 550 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", 551 __func__, us); 552 ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ 553 return AH_FALSE; 554 } else { 555 /* convert to system clocks */ 556 OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 557 AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); 558 ahp->ah_ctstimeout = us; 559 return AH_TRUE; 560 } 561 } 562 563 u_int 564 ar5212GetCTSTimeout(struct ath_hal *ah) 565 { 566 u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); 567 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 568 } 569 570 /* Setup decompression for given key index */ 571 HAL_BOOL 572 ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) 573 { 574 struct ath_hal_5212 *ahp = AH5212(ah); 575 576 if (keyidx >= HAL_DECOMP_MASK_SIZE) 577 return AH_FALSE; 578 OS_REG_WRITE(ah, AR_DCM_A, keyidx); 579 OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0); 580 ahp->ah_decompMask[keyidx] = en; 581 582 return AH_TRUE; 583 } 584 585 /* Setup coverage class */ 586 void 587 ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) 588 { 589 uint32_t slot, timeout, eifs; 590 u_int clkRate; 591 592 AH_PRIVATE(ah)->ah_coverageClass = coverageclass; 593 594 if (now) { 595 if (AH_PRIVATE(ah)->ah_coverageClass == 0) 596 return; 597 598 /* Don't apply coverage class to non A channels */ 599 if (!IEEE80211_IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan)) 600 return; 601 602 /* Get core clock rate */ 603 clkRate = ath_hal_mac_clks(ah, 1); 604 605 /* Compute EIFS */ 606 slot = coverageclass * 3 * clkRate; 607 eifs = coverageclass * 6 * clkRate; 608 if (IEEE80211_IS_CHAN_HALF(AH_PRIVATE(ah)->ah_curchan)) { 609 slot += IFS_SLOT_HALF_RATE; 610 eifs += IFS_EIFS_HALF_RATE; 611 } else if (IEEE80211_IS_CHAN_QUARTER(AH_PRIVATE(ah)->ah_curchan)) { 612 slot += IFS_SLOT_QUARTER_RATE; 613 eifs += IFS_EIFS_QUARTER_RATE; 614 } else { /* full rate */ 615 slot += IFS_SLOT_FULL_RATE; 616 eifs += IFS_EIFS_FULL_RATE; 617 } 618 619 /* 620 * Add additional time for air propagation for ACK and CTS 621 * timeouts. This value is in core clocks. 622 */ 623 timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate); 624 625 /* 626 * Write the values: slot, eifs, ack/cts timeouts. 627 */ 628 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); 629 OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); 630 OS_REG_WRITE(ah, AR_TIME_OUT, 631 SM(timeout, AR_TIME_OUT_CTS) 632 | SM(timeout, AR_TIME_OUT_ACK)); 633 } 634 } 635 636 HAL_STATUS 637 ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, 638 uint32_t nextStart, HAL_QUIET_FLAG flag) 639 { 640 OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S)); 641 if (flag & HAL_QUIET_ENABLE) { 642 OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16)); 643 } 644 else { 645 OS_REG_WRITE(ah, AR_QUIET1, nextStart); 646 } 647 return HAL_OK; 648 } 649 650 void 651 ar5212SetPCUConfig(struct ath_hal *ah) 652 { 653 ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); 654 } 655 656 /* 657 * Return whether an external 32KHz crystal should be used 658 * to reduce power consumption when sleeping. We do so if 659 * the crystal is present (obtained from EEPROM) and if we 660 * are not running as an AP and are configured to use it. 661 */ 662 HAL_BOOL 663 ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode) 664 { 665 if (opmode != HAL_M_HOSTAP) { 666 struct ath_hal_5212 *ahp = AH5212(ah); 667 return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) && 668 (ahp->ah_enable32kHzClock == USE_32KHZ || 669 ahp->ah_enable32kHzClock == AUTO_32KHZ); 670 } else 671 return AH_FALSE; 672 } 673 674 /* 675 * If 32KHz clock exists, use it to lower power consumption during sleep 676 * 677 * Note: If clock is set to 32 KHz, delays on accessing certain 678 * baseband registers (27-31, 124-127) are required. 679 */ 680 void 681 ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) 682 { 683 if (ar5212Use32KHzclock(ah, opmode)) { 684 /* 685 * Enable clocks to be turned OFF in BB during sleep 686 * and also enable turning OFF 32MHz/40MHz Refclk 687 * from A2. 688 */ 689 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); 690 OS_REG_WRITE(ah, AR_PHY_REFCLKPD, 691 IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); 692 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); 693 OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ 694 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1); 695 696 if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) { 697 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x26); 698 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0d); 699 OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x07); 700 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x3f); 701 /* # Set sleep clock rate to 32 KHz. */ 702 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2); 703 } else { 704 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0a); 705 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); 706 OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); 707 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x20); 708 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3); 709 } 710 } else { 711 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0); 712 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); 713 714 OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32MHz TSF inc */ 715 716 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); 717 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); 718 719 if (IS_2417(ah)) 720 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a); 721 else if (IS_HB63(ah)) 722 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32); 723 else 724 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); 725 OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); 726 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); 727 OS_REG_WRITE(ah, AR_PHY_REFCLKPD, 728 IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18); 729 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 730 IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); 731 } 732 } 733 734 /* 735 * If 32KHz clock exists, turn it off and turn back on the 32Mhz 736 */ 737 void 738 ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) 739 { 740 if (ar5212Use32KHzclock(ah, opmode)) { 741 /* # Set sleep clock rate back to 32 MHz. */ 742 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0); 743 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); 744 745 OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ 746 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 747 IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); 748 749 /* 750 * Restore BB registers to power-on defaults 751 */ 752 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); 753 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); 754 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); 755 OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); 756 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); 757 OS_REG_WRITE(ah, AR_PHY_REFCLKPD, 758 IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); 759 } 760 } 761 762 /* 763 * Adjust NF based on statistical values for 5GHz frequencies. 764 * Default method: this may be overridden by the rf backend. 765 */ 766 int16_t 767 ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) 768 { 769 static const struct { 770 uint16_t freqLow; 771 int16_t adjust; 772 } adjustDef[] = { 773 { 5790, 11 }, /* NB: ordered high -> low */ 774 { 5730, 10 }, 775 { 5690, 9 }, 776 { 5660, 8 }, 777 { 5610, 7 }, 778 { 5530, 5 }, 779 { 5450, 4 }, 780 { 5379, 2 }, 781 { 5209, 0 }, 782 { 3000, 1 }, 783 { 0, 0 }, 784 }; 785 int i; 786 787 for (i = 0; c->channel <= adjustDef[i].freqLow; i++) 788 ; 789 return adjustDef[i].adjust; 790 } 791 792 HAL_STATUS 793 ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 794 uint32_t capability, uint32_t *result) 795 { 796 #define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion 797 struct ath_hal_5212 *ahp = AH5212(ah); 798 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 799 const struct ar5212AniState *ani; 800 801 switch (type) { 802 case HAL_CAP_CIPHER: /* cipher handled in hardware */ 803 switch (capability) { 804 case HAL_CIPHER_AES_CCM: 805 return pCap->halCipherAesCcmSupport ? 806 HAL_OK : HAL_ENOTSUPP; 807 case HAL_CIPHER_AES_OCB: 808 case HAL_CIPHER_TKIP: 809 case HAL_CIPHER_WEP: 810 case HAL_CIPHER_MIC: 811 case HAL_CIPHER_CLR: 812 return HAL_OK; 813 default: 814 return HAL_ENOTSUPP; 815 } 816 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ 817 switch (capability) { 818 case 0: /* hardware capability */ 819 return HAL_OK; 820 case 1: 821 return (ahp->ah_staId1Defaults & 822 AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO; 823 } 824 return HAL_EINVAL; 825 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ 826 switch (capability) { 827 case 0: /* hardware capability */ 828 return pCap->halTkipMicTxRxKeySupport ? 829 HAL_ENXIO : HAL_OK; 830 case 1: /* current setting */ 831 return (ahp->ah_miscMode & 832 AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK; 833 } 834 return HAL_EINVAL; 835 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC w/ WMM */ 836 /* XXX move to capability bit */ 837 return MACVERSION(ah) > AR_SREV_VERSION_VENICE || 838 (MACVERSION(ah) == AR_SREV_VERSION_VENICE && 839 AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP; 840 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ 841 switch (capability) { 842 case 0: /* hardware capability */ 843 return HAL_OK; 844 case 1: /* current setting */ 845 return ahp->ah_diversity ? HAL_OK : HAL_ENXIO; 846 case HAL_CAP_STRONG_DIV: 847 *result = OS_REG_READ(ah, AR_PHY_RESTART); 848 *result = MS(*result, AR_PHY_RESTART_DIV_GC); 849 return HAL_OK; 850 } 851 return HAL_EINVAL; 852 case HAL_CAP_DIAG: 853 *result = AH_PRIVATE(ah)->ah_diagreg; 854 return HAL_OK; 855 case HAL_CAP_TPC: 856 switch (capability) { 857 case 0: /* hardware capability */ 858 return HAL_OK; 859 case 1: 860 return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO; 861 } 862 return HAL_OK; 863 case HAL_CAP_PHYDIAG: /* radar pulse detection capability */ 864 switch (capability) { 865 case HAL_CAP_RADAR: 866 return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ? 867 HAL_OK: HAL_ENXIO; 868 case HAL_CAP_AR: 869 return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) || 870 ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ? 871 HAL_OK: HAL_ENXIO; 872 } 873 return HAL_ENXIO; 874 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ 875 switch (capability) { 876 case 0: /* hardware capability */ 877 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENXIO; 878 case 1: 879 return (ahp->ah_staId1Defaults & 880 AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO; 881 } 882 return HAL_EINVAL; 883 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ 884 switch (capability) { 885 case 0: /* hardware capability */ 886 return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP; 887 case 1: 888 return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ? 889 HAL_OK : HAL_ENXIO; 890 } 891 return HAL_EINVAL; 892 case HAL_CAP_TPC_ACK: 893 *result = MS(ahp->ah_macTPC, AR_TPC_ACK); 894 return HAL_OK; 895 case HAL_CAP_TPC_CTS: 896 *result = MS(ahp->ah_macTPC, AR_TPC_CTS); 897 return HAL_OK; 898 case HAL_CAP_INTMIT: /* interference mitigation */ 899 switch (capability) { 900 case HAL_CAP_INTMIT_PRESENT: /* hardware capability */ 901 return HAL_OK; 902 case HAL_CAP_INTMIT_ENABLE: 903 return (ahp->ah_procPhyErr & HAL_ANI_ENA) ? 904 HAL_OK : HAL_ENXIO; 905 case HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL: 906 case HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL: 907 case HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR: 908 case HAL_CAP_INTMIT_FIRSTEP_LEVEL: 909 case HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL: 910 ani = ar5212AniGetCurrentState(ah); 911 if (ani == AH_NULL) 912 return HAL_ENXIO; 913 switch (capability) { 914 case 2: *result = ani->noiseImmunityLevel; break; 915 case 3: *result = !ani->ofdmWeakSigDetectOff; break; 916 case 4: *result = ani->cckWeakSigThreshold; break; 917 case 5: *result = ani->firstepLevel; break; 918 case 6: *result = ani->spurImmunityLevel; break; 919 } 920 return HAL_OK; 921 } 922 return HAL_EINVAL; 923 default: 924 return ath_hal_getcapability(ah, type, capability, result); 925 } 926 #undef MACVERSION 927 } 928 929 HAL_BOOL 930 ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 931 uint32_t capability, uint32_t setting, HAL_STATUS *status) 932 { 933 #define N(a) (sizeof(a)/sizeof(a[0])) 934 struct ath_hal_5212 *ahp = AH5212(ah); 935 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 936 uint32_t v; 937 938 switch (type) { 939 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ 940 if (setting) 941 ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE; 942 else 943 ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE; 944 return AH_TRUE; 945 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ 946 if (!pCap->halTkipMicTxRxKeySupport) 947 return AH_FALSE; 948 /* NB: true =>'s use split key cache layout */ 949 if (setting) 950 ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE; 951 else 952 ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE; 953 /* NB: write here so keys can be setup w/o a reset */ 954 OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); 955 return AH_TRUE; 956 case HAL_CAP_DIVERSITY: 957 switch (capability) { 958 case 0: 959 return AH_FALSE; 960 case 1: /* setting */ 961 if (ahp->ah_phyPowerOn) { 962 if (capability == HAL_CAP_STRONG_DIV) { 963 v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); 964 if (setting) 965 v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; 966 else 967 v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; 968 OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); 969 } 970 } 971 ahp->ah_diversity = (setting != 0); 972 return AH_TRUE; 973 974 case HAL_CAP_STRONG_DIV: 975 if (! ahp->ah_phyPowerOn) 976 return AH_FALSE; 977 v = OS_REG_READ(ah, AR_PHY_RESTART); 978 v &= ~AR_PHY_RESTART_DIV_GC; 979 v |= SM(setting, AR_PHY_RESTART_DIV_GC); 980 OS_REG_WRITE(ah, AR_PHY_RESTART, v); 981 return AH_TRUE; 982 default: 983 return AH_FALSE; 984 } 985 case HAL_CAP_DIAG: /* hardware diagnostic support */ 986 /* 987 * NB: could split this up into virtual capabilities, 988 * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly 989 * seems worth the additional complexity. 990 */ 991 AH_PRIVATE(ah)->ah_diagreg = setting; 992 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); 993 return AH_TRUE; 994 case HAL_CAP_TPC: 995 ahp->ah_tpcEnabled = (setting != 0); 996 return AH_TRUE; 997 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ 998 if (setting) 999 ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH; 1000 else 1001 ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH; 1002 return AH_TRUE; 1003 case HAL_CAP_TPC_ACK: 1004 case HAL_CAP_TPC_CTS: 1005 setting += ahp->ah_txPowerIndexOffset; 1006 if (setting > 63) 1007 setting = 63; 1008 if (type == HAL_CAP_TPC_ACK) { 1009 ahp->ah_macTPC &= AR_TPC_ACK; 1010 ahp->ah_macTPC |= MS(setting, AR_TPC_ACK); 1011 } else { 1012 ahp->ah_macTPC &= AR_TPC_CTS; 1013 ahp->ah_macTPC |= MS(setting, AR_TPC_CTS); 1014 } 1015 OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC); 1016 return AH_TRUE; 1017 case HAL_CAP_INTMIT: { /* interference mitigation */ 1018 /* This maps the public ANI commands to the internal ANI commands */ 1019 /* Private: HAL_ANI_CMD; Public: HAL_CAP_INTMIT_CMD */ 1020 static const HAL_ANI_CMD cmds[] = { 1021 HAL_ANI_PRESENT, 1022 HAL_ANI_MODE, 1023 HAL_ANI_NOISE_IMMUNITY_LEVEL, 1024 HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, 1025 HAL_ANI_CCK_WEAK_SIGNAL_THR, 1026 HAL_ANI_FIRSTEP_LEVEL, 1027 HAL_ANI_SPUR_IMMUNITY_LEVEL, 1028 }; 1029 return capability < N(cmds) ? 1030 AH5212(ah)->ah_aniControl(ah, cmds[capability], setting) : 1031 AH_FALSE; 1032 } 1033 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ 1034 if (pCap->halTsfAddSupport) { 1035 if (setting) 1036 ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF; 1037 else 1038 ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF; 1039 return AH_TRUE; 1040 } 1041 /* fall thru... */ 1042 default: 1043 return ath_hal_setcapability(ah, type, capability, 1044 setting, status); 1045 } 1046 #undef N 1047 } 1048 1049 HAL_BOOL 1050 ar5212GetDiagState(struct ath_hal *ah, int request, 1051 const void *args, uint32_t argsize, 1052 void **result, uint32_t *resultsize) 1053 { 1054 struct ath_hal_5212 *ahp = AH5212(ah); 1055 HAL_ANI_STATS *astats; 1056 1057 (void) ahp; 1058 if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) 1059 return AH_TRUE; 1060 switch (request) { 1061 case HAL_DIAG_EEPROM: 1062 case HAL_DIAG_EEPROM_EXP_11A: 1063 case HAL_DIAG_EEPROM_EXP_11B: 1064 case HAL_DIAG_EEPROM_EXP_11G: 1065 case HAL_DIAG_RFGAIN: 1066 return ath_hal_eepromDiag(ah, request, 1067 args, argsize, result, resultsize); 1068 case HAL_DIAG_RFGAIN_CURSTEP: 1069 *result = __DECONST(void *, ahp->ah_gainValues.currStep); 1070 *resultsize = (*result == AH_NULL) ? 1071 0 : sizeof(GAIN_OPTIMIZATION_STEP); 1072 return AH_TRUE; 1073 case HAL_DIAG_PCDAC: 1074 *result = ahp->ah_pcdacTable; 1075 *resultsize = ahp->ah_pcdacTableSize; 1076 return AH_TRUE; 1077 case HAL_DIAG_TXRATES: 1078 *result = &ahp->ah_ratesArray[0]; 1079 *resultsize = sizeof(ahp->ah_ratesArray); 1080 return AH_TRUE; 1081 case HAL_DIAG_ANI_CURRENT: 1082 *result = ar5212AniGetCurrentState(ah); 1083 *resultsize = (*result == AH_NULL) ? 1084 0 : sizeof(struct ar5212AniState); 1085 return AH_TRUE; 1086 case HAL_DIAG_ANI_STATS: 1087 OS_MEMZERO(&ahp->ext_ani_stats, sizeof(ahp->ext_ani_stats)); 1088 astats = ar5212AniGetCurrentStats(ah); 1089 if (astats == NULL) { 1090 *result = NULL; 1091 *resultsize = 0; 1092 } else { 1093 OS_MEMCPY(&ahp->ext_ani_stats, astats, sizeof(HAL_ANI_STATS)); 1094 *result = &ahp->ext_ani_stats; 1095 *resultsize = sizeof(ahp->ext_ani_stats); 1096 } 1097 return AH_TRUE; 1098 case HAL_DIAG_ANI_CMD: 1099 if (argsize != 2*sizeof(uint32_t)) 1100 return AH_FALSE; 1101 AH5212(ah)->ah_aniControl(ah, ((const uint32_t *)args)[0], 1102 ((const uint32_t *)args)[1]); 1103 return AH_TRUE; 1104 case HAL_DIAG_ANI_PARAMS: 1105 /* 1106 * NB: We assume struct ar5212AniParams is identical 1107 * to HAL_ANI_PARAMS; if they diverge then we'll need 1108 * to handle it here 1109 */ 1110 if (argsize == 0 && args == AH_NULL) { 1111 struct ar5212AniState *aniState = 1112 ar5212AniGetCurrentState(ah); 1113 if (aniState == AH_NULL) 1114 return AH_FALSE; 1115 *result = __DECONST(void *, aniState->params); 1116 *resultsize = sizeof(struct ar5212AniParams); 1117 return AH_TRUE; 1118 } else { 1119 if (argsize != sizeof(struct ar5212AniParams)) 1120 return AH_FALSE; 1121 return ar5212AniSetParams(ah, args, args); 1122 } 1123 break; 1124 } 1125 return AH_FALSE; 1126 } 1127 1128 /* 1129 * Check whether there's an in-progress NF completion. 1130 * 1131 * Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE 1132 * otherwise. 1133 */ 1134 HAL_BOOL 1135 ar5212IsNFCalInProgress(struct ath_hal *ah) 1136 { 1137 if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) 1138 return AH_TRUE; 1139 return AH_FALSE; 1140 } 1141 1142 /* 1143 * Wait for an in-progress NF calibration to complete. 1144 * 1145 * The completion function waits "i" times 10uS. 1146 * It returns AH_TRUE if the NF calibration completed (or was never 1147 * in progress); AH_FALSE if it was still in progress after "i" checks. 1148 */ 1149 HAL_BOOL 1150 ar5212WaitNFCalComplete(struct ath_hal *ah, int i) 1151 { 1152 int j; 1153 if (i <= 0) 1154 i = 1; /* it should run at least once */ 1155 for (j = 0; j < i; j++) { 1156 if (! ar5212IsNFCalInProgress(ah)) 1157 return AH_TRUE; 1158 OS_DELAY(10); 1159 } 1160 return AH_FALSE; 1161 } 1162 1163 void 1164 ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 1165 { 1166 uint32_t val; 1167 val = OS_REG_READ(ah, AR_PHY_RADAR_0); 1168 1169 if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { 1170 val &= ~AR_PHY_RADAR_0_FIRPWR; 1171 val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); 1172 } 1173 if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { 1174 val &= ~AR_PHY_RADAR_0_RRSSI; 1175 val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); 1176 } 1177 if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { 1178 val &= ~AR_PHY_RADAR_0_HEIGHT; 1179 val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); 1180 } 1181 if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { 1182 val &= ~AR_PHY_RADAR_0_PRSSI; 1183 val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); 1184 } 1185 if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { 1186 val &= ~AR_PHY_RADAR_0_INBAND; 1187 val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); 1188 } 1189 if (pe->pe_enabled) 1190 val |= AR_PHY_RADAR_0_ENA; 1191 else 1192 val &= ~ AR_PHY_RADAR_0_ENA; 1193 1194 if (IS_5413(ah)) { 1195 1196 if (pe->pe_blockradar == 1) 1197 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1198 AR_PHY_RADAR_2_BLOCKOFDMWEAK); 1199 else 1200 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1201 AR_PHY_RADAR_2_BLOCKOFDMWEAK); 1202 1203 if (pe->pe_en_relstep_check == 1) 1204 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1205 AR_PHY_RADAR_2_ENRELSTEPCHK); 1206 else 1207 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1208 AR_PHY_RADAR_2_ENRELSTEPCHK); 1209 1210 if (pe->pe_usefir128 == 1) 1211 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1212 AR_PHY_RADAR_2_USEFIR128); 1213 else 1214 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1215 AR_PHY_RADAR_2_USEFIR128); 1216 1217 if (pe->pe_enmaxrssi == 1) 1218 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1219 AR_PHY_RADAR_2_ENMAXRSSI); 1220 else 1221 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1222 AR_PHY_RADAR_2_ENMAXRSSI); 1223 1224 if (pe->pe_enrelpwr == 1) 1225 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1226 AR_PHY_RADAR_2_ENRELPWRCHK); 1227 else 1228 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1229 AR_PHY_RADAR_2_ENRELPWRCHK); 1230 1231 if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) 1232 OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, 1233 AR_PHY_RADAR_2_RELPWR, pe->pe_relpwr); 1234 1235 if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) 1236 OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, 1237 AR_PHY_RADAR_2_RELSTEP, pe->pe_relstep); 1238 1239 if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) 1240 OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, 1241 AR_PHY_RADAR_2_MAXLEN, pe->pe_maxlen); 1242 } 1243 1244 OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 1245 } 1246 1247 /* 1248 * Parameters for the AR5212 PHY. 1249 */ 1250 #define AR5212_DFS_FIRPWR -35 1251 #define AR5212_DFS_RRSSI 20 1252 #define AR5212_DFS_HEIGHT 14 1253 #define AR5212_DFS_PRSSI 6 1254 #define AR5212_DFS_INBAND 4 1255 1256 /* 1257 * Default parameters for the AR5413 PHY. 1258 */ 1259 #define AR5413_DFS_FIRPWR -34 1260 #define AR5413_DFS_RRSSI 20 1261 #define AR5413_DFS_HEIGHT 10 1262 #define AR5413_DFS_PRSSI 15 1263 #define AR5413_DFS_INBAND 6 1264 #define AR5413_DFS_RELPWR 8 1265 #define AR5413_DFS_RELSTEP 31 1266 #define AR5413_DFS_MAXLEN 255 1267 1268 HAL_BOOL 1269 ar5212GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 1270 { 1271 1272 if (IS_5413(ah)) { 1273 pe->pe_firpwr = AR5413_DFS_FIRPWR; 1274 pe->pe_rrssi = AR5413_DFS_RRSSI; 1275 pe->pe_height = AR5413_DFS_HEIGHT; 1276 pe->pe_prssi = AR5413_DFS_PRSSI; 1277 pe->pe_inband = AR5413_DFS_INBAND; 1278 pe->pe_relpwr = AR5413_DFS_RELPWR; 1279 pe->pe_relstep = AR5413_DFS_RELSTEP; 1280 pe->pe_maxlen = AR5413_DFS_MAXLEN; 1281 pe->pe_usefir128 = 0; 1282 pe->pe_blockradar = 1; 1283 pe->pe_enmaxrssi = 1; 1284 pe->pe_enrelpwr = 1; 1285 pe->pe_en_relstep_check = 0; 1286 } else { 1287 pe->pe_firpwr = AR5212_DFS_FIRPWR; 1288 pe->pe_rrssi = AR5212_DFS_RRSSI; 1289 pe->pe_height = AR5212_DFS_HEIGHT; 1290 pe->pe_prssi = AR5212_DFS_PRSSI; 1291 pe->pe_inband = AR5212_DFS_INBAND; 1292 pe->pe_relpwr = 0; 1293 pe->pe_relstep = 0; 1294 pe->pe_maxlen = 0; 1295 pe->pe_usefir128 = 0; 1296 pe->pe_blockradar = 0; 1297 pe->pe_enmaxrssi = 0; 1298 pe->pe_enrelpwr = 0; 1299 pe->pe_en_relstep_check = 0; 1300 } 1301 1302 return (AH_TRUE); 1303 } 1304 1305 void 1306 ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 1307 { 1308 uint32_t val,temp; 1309 1310 val = OS_REG_READ(ah, AR_PHY_RADAR_0); 1311 1312 temp = MS(val,AR_PHY_RADAR_0_FIRPWR); 1313 temp |= 0xFFFFFF80; 1314 pe->pe_firpwr = temp; 1315 pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); 1316 pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); 1317 pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); 1318 pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); 1319 pe->pe_enabled = !! (val & AR_PHY_RADAR_0_ENA); 1320 1321 pe->pe_relpwr = 0; 1322 pe->pe_relstep = 0; 1323 pe->pe_maxlen = 0; 1324 pe->pe_usefir128 = 0; 1325 pe->pe_blockradar = 0; 1326 pe->pe_enmaxrssi = 0; 1327 pe->pe_enrelpwr = 0; 1328 pe->pe_en_relstep_check = 0; 1329 pe->pe_extchannel = AH_FALSE; 1330 1331 if (IS_5413(ah)) { 1332 val = OS_REG_READ(ah, AR_PHY_RADAR_2); 1333 pe->pe_relpwr = !! MS(val, AR_PHY_RADAR_2_RELPWR); 1334 pe->pe_relstep = !! MS(val, AR_PHY_RADAR_2_RELSTEP); 1335 pe->pe_maxlen = !! MS(val, AR_PHY_RADAR_2_MAXLEN); 1336 1337 pe->pe_usefir128 = !! (val & AR_PHY_RADAR_2_USEFIR128); 1338 pe->pe_blockradar = !! (val & AR_PHY_RADAR_2_BLOCKOFDMWEAK); 1339 pe->pe_enmaxrssi = !! (val & AR_PHY_RADAR_2_ENMAXRSSI); 1340 pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_2_ENRELPWRCHK); 1341 pe->pe_en_relstep_check = 1342 !! (val & AR_PHY_RADAR_2_ENRELSTEPCHK); 1343 } 1344 } 1345 1346 /* 1347 * Process the radar phy error and extract the pulse duration. 1348 */ 1349 HAL_BOOL 1350 ar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, 1351 uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event) 1352 { 1353 uint8_t dur; 1354 uint8_t rssi; 1355 1356 /* Check whether the given phy error is a radar event */ 1357 if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) && 1358 (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) 1359 return AH_FALSE; 1360 1361 /* 1362 * The first byte is the pulse width - if there's 1363 * no data, simply set the duration to 0 1364 */ 1365 if (rxs->rs_datalen >= 1) 1366 /* The pulse width is byte 0 of the data */ 1367 dur = ((uint8_t) buf[0]) & 0xff; 1368 else 1369 dur = 0; 1370 1371 /* Pulse RSSI is the normal reported RSSI */ 1372 rssi = (uint8_t) rxs->rs_rssi; 1373 1374 /* 0 duration/rssi is not a valid radar event */ 1375 if (dur == 0 && rssi == 0) 1376 return AH_FALSE; 1377 1378 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", 1379 __func__, rssi, dur); 1380 1381 /* Record the event */ 1382 event->re_full_ts = fulltsf; 1383 event->re_ts = rxs->rs_tstamp; 1384 event->re_rssi = rssi; 1385 event->re_dur = dur; 1386 event->re_flags = HAL_DFS_EVENT_PRICH; 1387 1388 return AH_TRUE; 1389 } 1390 1391 /* 1392 * Return whether 5GHz fast-clock (44MHz) is enabled. 1393 * It's always disabled for AR5212 series NICs. 1394 */ 1395 HAL_BOOL 1396 ar5212IsFastClockEnabled(struct ath_hal *ah) 1397 { 1398 return AH_FALSE; 1399 } 1400 1401 /* 1402 * Return what percentage of the extension channel is busy. 1403 * This is always disabled for AR5212 series NICs. 1404 */ 1405 uint32_t 1406 ar5212Get11nExtBusy(struct ath_hal *ah) 1407 { 1408 return 0; 1409 } 1410 1411 /* 1412 * Channel survey support. 1413 */ 1414 HAL_BOOL 1415 ar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) 1416 { 1417 struct ath_hal_5212 *ahp = AH5212(ah); 1418 u_int32_t good = AH_TRUE; 1419 1420 /* XXX freeze/unfreeze mib counters */ 1421 uint32_t rc = OS_REG_READ(ah, AR_RCCNT); 1422 uint32_t rf = OS_REG_READ(ah, AR_RFCNT); 1423 uint32_t tf = OS_REG_READ(ah, AR_TFCNT); 1424 uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */ 1425 1426 if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) { 1427 /* 1428 * Cycle counter wrap (or initial call); it's not possible 1429 * to accurately calculate a value because the registers 1430 * right shift rather than wrap--so punt and return 0. 1431 */ 1432 HALDEBUG(ah, HAL_DEBUG_ANY, 1433 "%s: cycle counter wrap. ExtBusy = 0\n", __func__); 1434 good = AH_FALSE; 1435 } else { 1436 hsample->cycle_count = cc - ahp->ah_cycleCount; 1437 hsample->chan_busy = rc - ahp->ah_ctlBusy; 1438 hsample->ext_chan_busy = 0; 1439 hsample->rx_busy = rf - ahp->ah_rxBusy; 1440 hsample->tx_busy = tf - ahp->ah_txBusy; 1441 } 1442 1443 /* 1444 * Keep a copy of the MIB results so the next sample has something 1445 * to work from. 1446 */ 1447 ahp->ah_cycleCount = cc; 1448 ahp->ah_rxBusy = rf; 1449 ahp->ah_ctlBusy = rc; 1450 ahp->ah_txBusy = tf; 1451 1452 return (good); 1453 } 1454 1455 void 1456 ar5212SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask, 1457 uint32_t rx_chainmask) 1458 { 1459 } 1460