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