1 /* 2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2006 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 24 #include "ar5211/ar5211.h" 25 #include "ar5211/ar5211reg.h" 26 #include "ar5211/ar5211phy.h" 27 28 #include "ah_eeprom_v3.h" 29 30 #define AR_NUM_GPIO 6 /* 6 GPIO bits */ 31 #define AR_GPIOD_MASK 0x2f /* 6-bit mask */ 32 33 void 34 ar5211GetMacAddress(struct ath_hal *ah, uint8_t *mac) 35 { 36 struct ath_hal_5211 *ahp = AH5211(ah); 37 38 OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); 39 } 40 41 HAL_BOOL 42 ar5211SetMacAddress(struct ath_hal *ah, const uint8_t *mac) 43 { 44 struct ath_hal_5211 *ahp = AH5211(ah); 45 46 OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); 47 return AH_TRUE; 48 } 49 50 void 51 ar5211GetBssIdMask(struct ath_hal *ah, uint8_t *mask) 52 { 53 static const uint8_t ones[IEEE80211_ADDR_LEN] = 54 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 55 OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN); 56 } 57 58 HAL_BOOL 59 ar5211SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) 60 { 61 return AH_FALSE; 62 } 63 64 /* 65 * Read 16 bits of data from the specified EEPROM offset. 66 */ 67 HAL_BOOL 68 ar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) 69 { 70 OS_REG_WRITE(ah, AR_EEPROM_ADDR, off); 71 OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ); 72 73 if (!ath_hal_wait(ah, AR_EEPROM_STS, 74 AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR, 75 AR_EEPROM_STS_READ_COMPLETE)) { 76 HALDEBUG(ah, HAL_DEBUG_ANY, 77 "%s: read failed for entry 0x%x\n", __func__, off); 78 return AH_FALSE; 79 } 80 *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff; 81 return AH_TRUE; 82 } 83 84 #ifdef AH_SUPPORT_WRITE_EEPROM 85 /* 86 * Write 16 bits of data to the specified EEPROM offset. 87 */ 88 HAL_BOOL 89 ar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) 90 { 91 return AH_FALSE; 92 } 93 #endif /* AH_SUPPORT_WRITE_EEPROM */ 94 95 /* 96 * Attempt to change the cards operating regulatory domain to the given value 97 */ 98 HAL_BOOL 99 ar5211SetRegulatoryDomain(struct ath_hal *ah, 100 uint16_t regDomain, HAL_STATUS *status) 101 { 102 HAL_STATUS ecode; 103 104 if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { 105 ecode = HAL_EINVAL; 106 goto bad; 107 } 108 /* 109 * Check if EEPROM is configured to allow this; must 110 * be a proper version and the protection bits must 111 * permit re-writing that segment of the EEPROM. 112 */ 113 if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { 114 ecode = HAL_EEWRITE; 115 goto bad; 116 } 117 #ifdef AH_SUPPORT_WRITE_REGDOMAIN 118 if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { 119 HALDEBUG(ah, HAL_DEBUG_ANY, 120 "%s: set regulatory domain to %u (0x%x)\n", 121 __func__, regDomain, regDomain); 122 AH_PRIVATE(ah)->ah_currentRD = regDomain; 123 return AH_TRUE; 124 } 125 #endif 126 ecode = HAL_EIO; 127 bad: 128 if (status) 129 *status = ecode; 130 return AH_FALSE; 131 } 132 133 /* 134 * Return the wireless modes (a,b,g,t) supported by hardware. 135 * 136 * This value is what is actually supported by the hardware 137 * and is unaffected by regulatory/country code settings. 138 * 139 */ 140 u_int 141 ar5211GetWirelessModes(struct ath_hal *ah) 142 { 143 u_int mode = 0; 144 145 if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { 146 mode = HAL_MODE_11A; 147 if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) 148 mode |= HAL_MODE_TURBO | HAL_MODE_108A; 149 } 150 if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) 151 mode |= HAL_MODE_11B; 152 return mode; 153 } 154 155 #if 0 156 HAL_BOOL 157 ar5211GetTurboDisable(struct ath_hal *ah) 158 { 159 return (AH5211(ah)->ah_turboDisable != 0); 160 } 161 #endif 162 163 /* 164 * Called if RfKill is supported (according to EEPROM). Set the interrupt and 165 * GPIO values so the ISR and can disable RF on a switch signal 166 */ 167 void 168 ar5211EnableRfKill(struct ath_hal *ah) 169 { 170 uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; 171 int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); 172 int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); 173 174 /* 175 * Configure the desired GPIO port for input 176 * and enable baseband rf silence. 177 */ 178 ar5211GpioCfgInput(ah, select); 179 OS_REG_SET_BIT(ah, AR_PHY_BASE, 0x00002000); 180 /* 181 * If radio disable switch connection to GPIO bit x is enabled 182 * program GPIO interrupt. 183 * If rfkill bit on eeprom is 1, setupeeprommap routine has already 184 * verified that it is a later version of eeprom, it has a place for 185 * rfkill bit and it is set to 1, indicating that GPIO bit x hardware 186 * connection is present. 187 */ 188 ar5211GpioSetIntr(ah, select, (ar5211GpioGet(ah, select) != polarity)); 189 } 190 191 /* 192 * Configure GPIO Output lines 193 */ 194 HAL_BOOL 195 ar5211GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) 196 { 197 uint32_t reg; 198 199 HALASSERT(gpio < AR_NUM_GPIO); 200 201 reg = OS_REG_READ(ah, AR_GPIOCR); 202 reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); 203 reg |= AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT); 204 205 OS_REG_WRITE(ah, AR_GPIOCR, reg); 206 return AH_TRUE; 207 } 208 209 /* 210 * Configure GPIO Input lines 211 */ 212 HAL_BOOL 213 ar5211GpioCfgInput(struct ath_hal *ah, uint32_t gpio) 214 { 215 uint32_t reg; 216 217 HALASSERT(gpio < AR_NUM_GPIO); 218 219 reg = OS_REG_READ(ah, AR_GPIOCR); 220 reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); 221 reg |= AR_GPIOCR_0_CR_N << (gpio * AR_GPIOCR_CR_SHIFT); 222 223 OS_REG_WRITE(ah, AR_GPIOCR, reg); 224 return AH_TRUE; 225 } 226 227 /* 228 * Once configured for I/O - set output lines 229 */ 230 HAL_BOOL 231 ar5211GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) 232 { 233 uint32_t reg; 234 235 HALASSERT(gpio < AR_NUM_GPIO); 236 237 reg = OS_REG_READ(ah, AR_GPIODO); 238 reg &= ~(1 << gpio); 239 reg |= (val&1) << gpio; 240 241 OS_REG_WRITE(ah, AR_GPIODO, reg); 242 return AH_TRUE; 243 } 244 245 /* 246 * Once configured for I/O - get input lines 247 */ 248 uint32_t 249 ar5211GpioGet(struct ath_hal *ah, uint32_t gpio) 250 { 251 if (gpio < AR_NUM_GPIO) { 252 uint32_t val = OS_REG_READ(ah, AR_GPIODI); 253 val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; 254 return val; 255 } else { 256 return 0xffffffff; 257 } 258 } 259 260 /* 261 * Set the GPIO 0 Interrupt (gpio is ignored) 262 */ 263 void 264 ar5211GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) 265 { 266 uint32_t val = OS_REG_READ(ah, AR_GPIOCR); 267 268 /* Clear the bits that we will modify. */ 269 val &= ~(AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | 270 AR_GPIOCR_0_CR_A); 271 272 val |= AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_ENA; 273 if (ilevel) 274 val |= AR_GPIOCR_INT_SELH; 275 276 /* Don't need to change anything for low level interrupt. */ 277 OS_REG_WRITE(ah, AR_GPIOCR, val); 278 279 /* Change the interrupt mask. */ 280 ar5211SetInterrupts(ah, AH5211(ah)->ah_maskReg | HAL_INT_GPIO); 281 } 282 283 /* 284 * Change the LED blinking pattern to correspond to the connectivity 285 */ 286 void 287 ar5211SetLedState(struct ath_hal *ah, HAL_LED_STATE state) 288 { 289 static const uint32_t ledbits[8] = { 290 AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */ 291 AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */ 292 AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */ 293 AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/ 294 AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */ 295 AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, 296 AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, 297 AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, 298 }; 299 OS_REG_WRITE(ah, AR_PCICFG, 300 (OS_REG_READ(ah, AR_PCICFG) &~ 301 (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE)) 302 | ledbits[state & 0x7] 303 ); 304 } 305 306 /* 307 * Change association related fields programmed into the hardware. 308 * Writing a valid BSSID to the hardware effectively enables the hardware 309 * to synchronize its TSF to the correct beacons and receive frames coming 310 * from that BSSID. It is called by the SME JOIN operation. 311 */ 312 void 313 ar5211WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) 314 { 315 struct ath_hal_5211 *ahp = AH5211(ah); 316 317 /* XXX save bssid for possible re-use on reset */ 318 OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); 319 OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); 320 OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | 321 ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S)); 322 } 323 324 /* 325 * Get the current hardware tsf for stamlme. 326 */ 327 uint64_t 328 ar5211GetTsf64(struct ath_hal *ah) 329 { 330 uint32_t low1, low2, u32; 331 332 /* sync multi-word read */ 333 low1 = OS_REG_READ(ah, AR_TSF_L32); 334 u32 = OS_REG_READ(ah, AR_TSF_U32); 335 low2 = OS_REG_READ(ah, AR_TSF_L32); 336 if (low2 < low1) { /* roll over */ 337 /* 338 * If we are not preempted this will work. If we are 339 * then we re-reading AR_TSF_U32 does no good as the 340 * low bits will be meaningless. Likewise reading 341 * L32, U32, U32, then comparing the last two reads 342 * to check for rollover doesn't help if preempted--so 343 * we take this approach as it costs one less PCI 344 * read which can be noticeable when doing things 345 * like timestamping packets in monitor mode. 346 */ 347 u32++; 348 } 349 return (((uint64_t) u32) << 32) | ((uint64_t) low2); 350 } 351 352 /* 353 * Get the current hardware tsf for stamlme. 354 */ 355 uint32_t 356 ar5211GetTsf32(struct ath_hal *ah) 357 { 358 return OS_REG_READ(ah, AR_TSF_L32); 359 } 360 361 /* 362 * Reset the current hardware tsf for stamlme 363 */ 364 void 365 ar5211ResetTsf(struct ath_hal *ah) 366 { 367 uint32_t val = OS_REG_READ(ah, AR_BEACON); 368 369 OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); 370 } 371 372 /* 373 * Grab a semi-random value from hardware registers - may not 374 * change often 375 */ 376 uint32_t 377 ar5211GetRandomSeed(struct ath_hal *ah) 378 { 379 uint32_t nf; 380 381 nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; 382 if (nf & 0x100) 383 nf = 0 - ((nf ^ 0x1ff) + 1); 384 return (OS_REG_READ(ah, AR_TSF_U32) ^ 385 OS_REG_READ(ah, AR_TSF_L32) ^ nf); 386 } 387 388 /* 389 * Detect if our card is present 390 */ 391 HAL_BOOL 392 ar5211DetectCardPresent(struct ath_hal *ah) 393 { 394 uint16_t macVersion, macRev; 395 uint32_t v; 396 397 /* 398 * Read the Silicon Revision register and compare that 399 * to what we read at attach time. If the same, we say 400 * a card/device is present. 401 */ 402 v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; 403 macVersion = v >> AR_SREV_ID_S; 404 macRev = v & AR_SREV_REVISION_M; 405 return (AH_PRIVATE(ah)->ah_macVersion == macVersion && 406 AH_PRIVATE(ah)->ah_macRev == macRev); 407 } 408 409 /* 410 * Update MIB Counters 411 */ 412 void 413 ar5211UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) 414 { 415 stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); 416 stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); 417 stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); 418 stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); 419 stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); 420 } 421 422 HAL_BOOL 423 ar5211SetSifsTime(struct ath_hal *ah, u_int us) 424 { 425 struct ath_hal_5211 *ahp = AH5211(ah); 426 427 if (us > ath_hal_mac_usec(ah, 0xffff)) { 428 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", 429 __func__, us); 430 ahp->ah_sifstime = (u_int) -1; /* restore default handling */ 431 return AH_FALSE; 432 } else { 433 /* convert to system clocks */ 434 OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us)); 435 ahp->ah_slottime = us; 436 return AH_TRUE; 437 } 438 } 439 440 u_int 441 ar5211GetSifsTime(struct ath_hal *ah) 442 { 443 u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; 444 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 445 } 446 447 HAL_BOOL 448 ar5211SetSlotTime(struct ath_hal *ah, u_int us) 449 { 450 struct ath_hal_5211 *ahp = AH5211(ah); 451 452 if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { 453 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", 454 __func__, us); 455 ahp->ah_slottime = us; /* restore default handling */ 456 return AH_FALSE; 457 } else { 458 /* convert to system clocks */ 459 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); 460 ahp->ah_slottime = us; 461 return AH_TRUE; 462 } 463 } 464 465 u_int 466 ar5211GetSlotTime(struct ath_hal *ah) 467 { 468 u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; 469 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 470 } 471 472 HAL_BOOL 473 ar5211SetAckTimeout(struct ath_hal *ah, u_int us) 474 { 475 struct ath_hal_5211 *ahp = AH5211(ah); 476 477 if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { 478 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", 479 __func__, us); 480 ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ 481 return AH_FALSE; 482 } else { 483 /* convert to system clocks */ 484 OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 485 AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); 486 ahp->ah_acktimeout = us; 487 return AH_TRUE; 488 } 489 } 490 491 u_int 492 ar5211GetAckTimeout(struct ath_hal *ah) 493 { 494 u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); 495 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 496 } 497 498 u_int 499 ar5211GetAckCTSRate(struct ath_hal *ah) 500 { 501 return ((AH5211(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); 502 } 503 504 HAL_BOOL 505 ar5211SetAckCTSRate(struct ath_hal *ah, u_int high) 506 { 507 struct ath_hal_5211 *ahp = AH5211(ah); 508 509 if (high) { 510 OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 511 ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; 512 } else { 513 OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 514 ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; 515 } 516 return AH_TRUE; 517 } 518 519 HAL_BOOL 520 ar5211SetCTSTimeout(struct ath_hal *ah, u_int us) 521 { 522 struct ath_hal_5211 *ahp = AH5211(ah); 523 524 if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { 525 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", 526 __func__, us); 527 ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ 528 return AH_FALSE; 529 } else { 530 /* convert to system clocks */ 531 OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 532 AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); 533 ahp->ah_ctstimeout = us; 534 return AH_TRUE; 535 } 536 } 537 538 u_int 539 ar5211GetCTSTimeout(struct ath_hal *ah) 540 { 541 u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); 542 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 543 } 544 545 HAL_BOOL 546 ar5211SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) 547 { 548 /* nothing to do */ 549 return AH_TRUE; 550 } 551 552 void 553 ar5211SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) 554 { 555 } 556 557 /* 558 * Control Adaptive Noise Immunity Parameters 559 */ 560 HAL_BOOL 561 ar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) 562 { 563 return AH_FALSE; 564 } 565 566 void 567 ar5211AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) 568 { 569 } 570 571 void 572 ar5211RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, 573 const struct ieee80211_channel *chan) 574 { 575 } 576 577 void 578 ar5211MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) 579 { 580 } 581 582 /* 583 * Get the rssi of frame curently being received. 584 */ 585 uint32_t 586 ar5211GetCurRssi(struct ath_hal *ah) 587 { 588 return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); 589 } 590 591 u_int 592 ar5211GetDefAntenna(struct ath_hal *ah) 593 { 594 return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); 595 } 596 597 void 598 ar5211SetDefAntenna(struct ath_hal *ah, u_int antenna) 599 { 600 OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); 601 } 602 603 HAL_ANT_SETTING 604 ar5211GetAntennaSwitch(struct ath_hal *ah) 605 { 606 return AH5211(ah)->ah_diversityControl; 607 } 608 609 HAL_BOOL 610 ar5211SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) 611 { 612 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 613 614 if (chan == AH_NULL) { 615 AH5211(ah)->ah_diversityControl = settings; 616 return AH_TRUE; 617 } 618 return ar5211SetAntennaSwitchInternal(ah, settings, chan); 619 } 620 621 HAL_STATUS 622 ar5211GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 623 uint32_t capability, uint32_t *result) 624 { 625 626 switch (type) { 627 case HAL_CAP_CIPHER: /* cipher handled in hardware */ 628 switch (capability) { 629 case HAL_CIPHER_AES_OCB: 630 case HAL_CIPHER_WEP: 631 case HAL_CIPHER_CLR: 632 return HAL_OK; 633 default: 634 return HAL_ENOTSUPP; 635 } 636 default: 637 return ath_hal_getcapability(ah, type, capability, result); 638 } 639 } 640 641 HAL_BOOL 642 ar5211SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 643 uint32_t capability, uint32_t setting, HAL_STATUS *status) 644 { 645 switch (type) { 646 case HAL_CAP_DIAG: /* hardware diagnostic support */ 647 /* 648 * NB: could split this up into virtual capabilities, 649 * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly 650 * seems worth the additional complexity. 651 */ 652 #ifdef AH_DEBUG 653 AH_PRIVATE(ah)->ah_diagreg = setting; 654 #else 655 AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ 656 #endif 657 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); 658 return AH_TRUE; 659 default: 660 return ath_hal_setcapability(ah, type, capability, 661 setting, status); 662 } 663 } 664 665 HAL_BOOL 666 ar5211GetDiagState(struct ath_hal *ah, int request, 667 const void *args, uint32_t argsize, 668 void **result, uint32_t *resultsize) 669 { 670 struct ath_hal_5211 *ahp = AH5211(ah); 671 672 (void) ahp; 673 if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) 674 return AH_TRUE; 675 switch (request) { 676 case HAL_DIAG_EEPROM: 677 return ath_hal_eepromDiag(ah, request, 678 args, argsize, result, resultsize); 679 case HAL_DIAG_RFGAIN: 680 *result = &ahp->ah_gainValues; 681 *resultsize = sizeof(GAIN_VALUES); 682 return AH_TRUE; 683 case HAL_DIAG_RFGAIN_CURSTEP: 684 *result = __DECONST(void *, ahp->ah_gainValues.currStep); 685 *resultsize = (*result == AH_NULL) ? 686 0 : sizeof(GAIN_OPTIMIZATION_STEP); 687 return AH_TRUE; 688 } 689 return AH_FALSE; 690 } 691 692 /* 693 * Return what percentage of the extension channel is busy. 694 * This is always disabled for AR5211 series NICs. 695 */ 696 uint32_t 697 ar5211Get11nExtBusy(struct ath_hal *ah) 698 { 699 return (0); 700 } 701 702 703 /* 704 * There's no channel survey support for the AR5211. 705 */ 706 HAL_BOOL 707 ar5211GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) 708 { 709 710 return (AH_FALSE); 711 } 712 713 void 714 ar5211SetChainMasks(struct ath_hal *ah, uint32_t txchainmask, 715 uint32_t rxchainmask) 716 { 717 } 718 719 void 720 ar5211EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 721 { 722 } 723 724 void 725 ar5211GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 726 { 727 } 728