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