ar5211_misc.c revision 187831
1185377Ssam/* 2187831Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3185377Ssam * Copyright (c) 2002-2006 Atheros Communications, Inc. 4185377Ssam * 5185377Ssam * Permission to use, copy, modify, and/or distribute this software for any 6185377Ssam * purpose with or without fee is hereby granted, provided that the above 7185377Ssam * copyright notice and this permission notice appear in all copies. 8185377Ssam * 9185377Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10185377Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11185377Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12185377Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13185377Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14185377Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15185377Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16185377Ssam * 17187510Ssam * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c 187831 2009-01-28 18:00:22Z sam $ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam 24185377Ssam#include "ar5211/ar5211.h" 25185377Ssam#include "ar5211/ar5211reg.h" 26185377Ssam#include "ar5211/ar5211phy.h" 27185377Ssam 28185377Ssam#include "ah_eeprom_v3.h" 29185377Ssam 30185377Ssam#define AR_NUM_GPIO 6 /* 6 GPIO bits */ 31185377Ssam#define AR_GPIOD_MASK 0x2f /* 6-bit mask */ 32185377Ssam 33185377Ssamvoid 34185377Ssamar5211GetMacAddress(struct ath_hal *ah, uint8_t *mac) 35185377Ssam{ 36185377Ssam struct ath_hal_5211 *ahp = AH5211(ah); 37185377Ssam 38185377Ssam OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); 39185377Ssam} 40185377Ssam 41185377SsamHAL_BOOL 42185377Ssamar5211SetMacAddress(struct ath_hal *ah, const uint8_t *mac) 43185377Ssam{ 44185377Ssam struct ath_hal_5211 *ahp = AH5211(ah); 45185377Ssam 46185377Ssam OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); 47185377Ssam return AH_TRUE; 48185377Ssam} 49185377Ssam 50185377Ssamvoid 51185377Ssamar5211GetBssIdMask(struct ath_hal *ah, uint8_t *mask) 52185377Ssam{ 53185377Ssam static const uint8_t ones[IEEE80211_ADDR_LEN] = 54185377Ssam { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 55185377Ssam OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN); 56185377Ssam} 57185377Ssam 58185377SsamHAL_BOOL 59185377Ssamar5211SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) 60185377Ssam{ 61185377Ssam return AH_FALSE; 62185377Ssam} 63185377Ssam 64185377Ssam/* 65185377Ssam * Read 16 bits of data from the specified EEPROM offset. 66185377Ssam */ 67185377SsamHAL_BOOL 68185377Ssamar5211EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) 69185377Ssam{ 70185377Ssam OS_REG_WRITE(ah, AR_EEPROM_ADDR, off); 71185377Ssam OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ); 72185377Ssam 73185377Ssam if (!ath_hal_wait(ah, AR_EEPROM_STS, 74185377Ssam AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR, 75185377Ssam AR_EEPROM_STS_READ_COMPLETE)) { 76185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 77185377Ssam "%s: read failed for entry 0x%x\n", __func__, off); 78185377Ssam return AH_FALSE; 79185377Ssam } 80185377Ssam *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff; 81185377Ssam return AH_TRUE; 82185377Ssam} 83185377Ssam 84185380Ssam#ifdef AH_SUPPORT_WRITE_EEPROM 85185377Ssam/* 86185380Ssam * Write 16 bits of data to the specified EEPROM offset. 87185380Ssam */ 88185380SsamHAL_BOOL 89185380Ssamar5211EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) 90185380Ssam{ 91185380Ssam return AH_FALSE; 92185380Ssam} 93185380Ssam#endif /* AH_SUPPORT_WRITE_EEPROM */ 94185380Ssam 95185380Ssam/* 96185380Ssam * Attempt to change the cards operating regulatory domain to the given value 97185380Ssam */ 98185380SsamHAL_BOOL 99185380Ssamar5211SetRegulatoryDomain(struct ath_hal *ah, 100185380Ssam uint16_t regDomain, HAL_STATUS *status) 101185380Ssam{ 102185380Ssam HAL_STATUS ecode; 103185380Ssam 104185380Ssam if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { 105185380Ssam ecode = HAL_EINVAL; 106185380Ssam goto bad; 107185380Ssam } 108185380Ssam /* 109185380Ssam * Check if EEPROM is configured to allow this; must 110185380Ssam * be a proper version and the protection bits must 111185380Ssam * permit re-writing that segment of the EEPROM. 112185380Ssam */ 113185380Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { 114185380Ssam ecode = HAL_EEWRITE; 115185380Ssam goto bad; 116185380Ssam } 117185380Ssam#ifdef AH_SUPPORT_WRITE_REGDOMAIN 118185380Ssam if (ar5211EepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { 119185380Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 120185380Ssam "%s: set regulatory domain to %u (0x%x)\n", 121185380Ssam __func__, regDomain, regDomain); 122185380Ssam AH_PRIVATE(ah)->ah_currentRD = regDomain; 123185380Ssam return AH_TRUE; 124185380Ssam } 125185380Ssam#endif 126185380Ssam ecode = HAL_EIO; 127185380Ssambad: 128185380Ssam if (status) 129185380Ssam *status = ecode; 130185380Ssam return AH_FALSE; 131185380Ssam} 132185380Ssam 133185380Ssam/* 134185377Ssam * Return the wireless modes (a,b,g,t) supported by hardware. 135185377Ssam * 136185377Ssam * This value is what is actually supported by the hardware 137185377Ssam * and is unaffected by regulatory/country code settings. 138185377Ssam * 139185377Ssam */ 140185377Ssamu_int 141185377Ssamar5211GetWirelessModes(struct ath_hal *ah) 142185377Ssam{ 143185377Ssam u_int mode = 0; 144185377Ssam 145185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { 146185377Ssam mode = HAL_MODE_11A; 147185377Ssam if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) 148185377Ssam mode |= HAL_MODE_TURBO | HAL_MODE_108A; 149185377Ssam } 150185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) 151185377Ssam mode |= HAL_MODE_11B; 152185377Ssam return mode; 153185377Ssam} 154185377Ssam 155185377Ssam#if 0 156185377SsamHAL_BOOL 157185377Ssamar5211GetTurboDisable(struct ath_hal *ah) 158185377Ssam{ 159185377Ssam return (AH5211(ah)->ah_turboDisable != 0); 160185377Ssam} 161185377Ssam#endif 162185377Ssam 163185377Ssam/* 164185377Ssam * Called if RfKill is supported (according to EEPROM). Set the interrupt and 165185377Ssam * GPIO values so the ISR and can disable RF on a switch signal 166185377Ssam */ 167185377Ssamvoid 168185377Ssamar5211EnableRfKill(struct ath_hal *ah) 169185377Ssam{ 170185377Ssam uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; 171185377Ssam int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); 172185377Ssam int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); 173185377Ssam 174185377Ssam /* 175185377Ssam * Configure the desired GPIO port for input 176185377Ssam * and enable baseband rf silence. 177185377Ssam */ 178185377Ssam ar5211GpioCfgInput(ah, select); 179185377Ssam OS_REG_SET_BIT(ah, AR_PHY_BASE, 0x00002000); 180185377Ssam /* 181185377Ssam * If radio disable switch connection to GPIO bit x is enabled 182185377Ssam * program GPIO interrupt. 183185377Ssam * If rfkill bit on eeprom is 1, setupeeprommap routine has already 184185377Ssam * verified that it is a later version of eeprom, it has a place for 185185377Ssam * rfkill bit and it is set to 1, indicating that GPIO bit x hardware 186185377Ssam * connection is present. 187185377Ssam */ 188185377Ssam ar5211GpioSetIntr(ah, select, (ar5211GpioGet(ah, select) != polarity)); 189185377Ssam} 190185377Ssam 191185377Ssam/* 192185377Ssam * Configure GPIO Output lines 193185377Ssam */ 194185377SsamHAL_BOOL 195185377Ssamar5211GpioCfgOutput(struct ath_hal *ah, uint32_t gpio) 196185377Ssam{ 197185377Ssam uint32_t reg; 198185377Ssam 199185377Ssam HALASSERT(gpio < AR_NUM_GPIO); 200185377Ssam 201185377Ssam reg = OS_REG_READ(ah, AR_GPIOCR); 202185377Ssam reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); 203185377Ssam reg |= AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT); 204185377Ssam 205185377Ssam OS_REG_WRITE(ah, AR_GPIOCR, reg); 206185377Ssam return AH_TRUE; 207185377Ssam} 208185377Ssam 209185377Ssam/* 210185377Ssam * Configure GPIO Input lines 211185377Ssam */ 212185377SsamHAL_BOOL 213185377Ssamar5211GpioCfgInput(struct ath_hal *ah, uint32_t gpio) 214185377Ssam{ 215185377Ssam uint32_t reg; 216185377Ssam 217185377Ssam HALASSERT(gpio < AR_NUM_GPIO); 218185377Ssam 219185377Ssam reg = OS_REG_READ(ah, AR_GPIOCR); 220185377Ssam reg &= ~(AR_GPIOCR_0_CR_A << (gpio * AR_GPIOCR_CR_SHIFT)); 221185377Ssam reg |= AR_GPIOCR_0_CR_N << (gpio * AR_GPIOCR_CR_SHIFT); 222185377Ssam 223185377Ssam OS_REG_WRITE(ah, AR_GPIOCR, reg); 224185377Ssam return AH_TRUE; 225185377Ssam} 226185377Ssam 227185377Ssam/* 228185377Ssam * Once configured for I/O - set output lines 229185377Ssam */ 230185377SsamHAL_BOOL 231185377Ssamar5211GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) 232185377Ssam{ 233185377Ssam uint32_t reg; 234185377Ssam 235185377Ssam HALASSERT(gpio < AR_NUM_GPIO); 236185377Ssam 237185377Ssam reg = OS_REG_READ(ah, AR_GPIODO); 238185377Ssam reg &= ~(1 << gpio); 239185377Ssam reg |= (val&1) << gpio; 240185377Ssam 241185377Ssam OS_REG_WRITE(ah, AR_GPIODO, reg); 242185377Ssam return AH_TRUE; 243185377Ssam} 244185377Ssam 245185377Ssam/* 246185377Ssam * Once configured for I/O - get input lines 247185377Ssam */ 248185377Ssamuint32_t 249185377Ssamar5211GpioGet(struct ath_hal *ah, uint32_t gpio) 250185377Ssam{ 251185377Ssam if (gpio < AR_NUM_GPIO) { 252185377Ssam uint32_t val = OS_REG_READ(ah, AR_GPIODI); 253185377Ssam val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; 254185377Ssam return val; 255185377Ssam } else { 256185377Ssam return 0xffffffff; 257185377Ssam } 258185377Ssam} 259185377Ssam 260185377Ssam/* 261185377Ssam * Set the GPIO 0 Interrupt (gpio is ignored) 262185377Ssam */ 263185377Ssamvoid 264185377Ssamar5211GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) 265185377Ssam{ 266185377Ssam uint32_t val = OS_REG_READ(ah, AR_GPIOCR); 267185377Ssam 268185377Ssam /* Clear the bits that we will modify. */ 269185377Ssam val &= ~(AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | 270185377Ssam AR_GPIOCR_0_CR_A); 271185377Ssam 272185377Ssam val |= AR_GPIOCR_INT_SEL0 | AR_GPIOCR_INT_ENA; 273185377Ssam if (ilevel) 274185377Ssam val |= AR_GPIOCR_INT_SELH; 275185377Ssam 276185377Ssam /* Don't need to change anything for low level interrupt. */ 277185377Ssam OS_REG_WRITE(ah, AR_GPIOCR, val); 278185377Ssam 279185377Ssam /* Change the interrupt mask. */ 280185377Ssam ar5211SetInterrupts(ah, AH5211(ah)->ah_maskReg | HAL_INT_GPIO); 281185377Ssam} 282185377Ssam 283185377Ssam/* 284185377Ssam * Change the LED blinking pattern to correspond to the connectivity 285185377Ssam */ 286185377Ssamvoid 287185377Ssamar5211SetLedState(struct ath_hal *ah, HAL_LED_STATE state) 288185377Ssam{ 289185377Ssam static const uint32_t ledbits[8] = { 290185377Ssam AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_INIT */ 291185377Ssam AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_SCAN */ 292185377Ssam AR_PCICFG_LEDCTL_PEND|AR_PCICFG_LEDMODE_PROP, /* HAL_LED_AUTH */ 293185377Ssam AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_ASSOC*/ 294185377Ssam AR_PCICFG_LEDCTL_ASSOC|AR_PCICFG_LEDMODE_PROP,/* HAL_LED_RUN */ 295185377Ssam AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, 296185377Ssam AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, 297185377Ssam AR_PCICFG_LEDCTL_NONE|AR_PCICFG_LEDMODE_RAND, 298185377Ssam }; 299185377Ssam OS_REG_WRITE(ah, AR_PCICFG, 300185377Ssam (OS_REG_READ(ah, AR_PCICFG) &~ 301185377Ssam (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE)) 302185377Ssam | ledbits[state & 0x7] 303185377Ssam ); 304185377Ssam} 305185377Ssam 306185377Ssam/* 307185377Ssam * Change association related fields programmed into the hardware. 308185377Ssam * Writing a valid BSSID to the hardware effectively enables the hardware 309185377Ssam * to synchronize its TSF to the correct beacons and receive frames coming 310185377Ssam * from that BSSID. It is called by the SME JOIN operation. 311185377Ssam */ 312185377Ssamvoid 313185377Ssamar5211WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) 314185377Ssam{ 315185377Ssam struct ath_hal_5211 *ahp = AH5211(ah); 316185377Ssam 317185377Ssam /* XXX save bssid for possible re-use on reset */ 318185377Ssam OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); 319185377Ssam OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); 320185377Ssam OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | 321185377Ssam ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S)); 322185377Ssam} 323185377Ssam 324185377Ssam/* 325185377Ssam * Get the current hardware tsf for stamlme. 326185377Ssam */ 327185377Ssamuint64_t 328185377Ssamar5211GetTsf64(struct ath_hal *ah) 329185377Ssam{ 330185377Ssam uint32_t low1, low2, u32; 331185377Ssam 332185377Ssam /* sync multi-word read */ 333185377Ssam low1 = OS_REG_READ(ah, AR_TSF_L32); 334185377Ssam u32 = OS_REG_READ(ah, AR_TSF_U32); 335185377Ssam low2 = OS_REG_READ(ah, AR_TSF_L32); 336185377Ssam if (low2 < low1) { /* roll over */ 337185377Ssam /* 338185377Ssam * If we are not preempted this will work. If we are 339185377Ssam * then we re-reading AR_TSF_U32 does no good as the 340185377Ssam * low bits will be meaningless. Likewise reading 341185377Ssam * L32, U32, U32, then comparing the last two reads 342185380Ssam * to check for rollover doesn't help if preempted--so 343185380Ssam * we take this approach as it costs one less PCI 344185380Ssam * read which can be noticeable when doing things 345185380Ssam * like timestamping packets in monitor mode. 346185377Ssam */ 347185377Ssam u32++; 348185377Ssam } 349185377Ssam return (((uint64_t) u32) << 32) | ((uint64_t) low2); 350185377Ssam} 351185377Ssam 352185377Ssam/* 353185377Ssam * Get the current hardware tsf for stamlme. 354185377Ssam */ 355185377Ssamuint32_t 356185377Ssamar5211GetTsf32(struct ath_hal *ah) 357185377Ssam{ 358185377Ssam return OS_REG_READ(ah, AR_TSF_L32); 359185377Ssam} 360185377Ssam 361185377Ssam/* 362185377Ssam * Reset the current hardware tsf for stamlme 363185377Ssam */ 364185377Ssamvoid 365185377Ssamar5211ResetTsf(struct ath_hal *ah) 366185377Ssam{ 367185377Ssam uint32_t val = OS_REG_READ(ah, AR_BEACON); 368185377Ssam 369185377Ssam OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); 370185377Ssam} 371185377Ssam 372185377Ssam/* 373185377Ssam * Grab a semi-random value from hardware registers - may not 374185377Ssam * change often 375185377Ssam */ 376185377Ssamuint32_t 377185377Ssamar5211GetRandomSeed(struct ath_hal *ah) 378185377Ssam{ 379185377Ssam uint32_t nf; 380185377Ssam 381185377Ssam nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; 382185377Ssam if (nf & 0x100) 383185377Ssam nf = 0 - ((nf ^ 0x1ff) + 1); 384185377Ssam return (OS_REG_READ(ah, AR_TSF_U32) ^ 385185377Ssam OS_REG_READ(ah, AR_TSF_L32) ^ nf); 386185377Ssam} 387185377Ssam 388185377Ssam/* 389185377Ssam * Detect if our card is present 390185377Ssam */ 391185377SsamHAL_BOOL 392185377Ssamar5211DetectCardPresent(struct ath_hal *ah) 393185377Ssam{ 394185377Ssam uint16_t macVersion, macRev; 395185377Ssam uint32_t v; 396185377Ssam 397185377Ssam /* 398185377Ssam * Read the Silicon Revision register and compare that 399185377Ssam * to what we read at attach time. If the same, we say 400185377Ssam * a card/device is present. 401185377Ssam */ 402185377Ssam v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; 403185377Ssam macVersion = v >> AR_SREV_ID_S; 404185377Ssam macRev = v & AR_SREV_REVISION_M; 405185377Ssam return (AH_PRIVATE(ah)->ah_macVersion == macVersion && 406185377Ssam AH_PRIVATE(ah)->ah_macRev == macRev); 407185377Ssam} 408185377Ssam 409185377Ssam/* 410185377Ssam * Update MIB Counters 411185377Ssam */ 412185377Ssamvoid 413185377Ssamar5211UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) 414185377Ssam{ 415185377Ssam stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); 416185377Ssam stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); 417185377Ssam stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); 418185377Ssam stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); 419185377Ssam stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); 420185377Ssam} 421185377Ssam 422185377SsamHAL_BOOL 423185377Ssamar5211SetSifsTime(struct ath_hal *ah, u_int us) 424185377Ssam{ 425185377Ssam struct ath_hal_5211 *ahp = AH5211(ah); 426185377Ssam 427185377Ssam if (us > ath_hal_mac_usec(ah, 0xffff)) { 428185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", 429185377Ssam __func__, us); 430185377Ssam ahp->ah_sifstime = (u_int) -1; /* restore default handling */ 431185377Ssam return AH_FALSE; 432185377Ssam } else { 433185377Ssam /* convert to system clocks */ 434185377Ssam OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us)); 435187831Ssam ahp->ah_slottime = us; 436185377Ssam return AH_TRUE; 437185377Ssam } 438185377Ssam} 439185377Ssam 440185377Ssamu_int 441185377Ssamar5211GetSifsTime(struct ath_hal *ah) 442185377Ssam{ 443185377Ssam u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; 444185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 445185377Ssam} 446185377Ssam 447185377SsamHAL_BOOL 448185377Ssamar5211SetSlotTime(struct ath_hal *ah, u_int us) 449185377Ssam{ 450185377Ssam struct ath_hal_5211 *ahp = AH5211(ah); 451185377Ssam 452185377Ssam if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { 453185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", 454185377Ssam __func__, us); 455185377Ssam ahp->ah_slottime = us; /* restore default handling */ 456185377Ssam return AH_FALSE; 457185377Ssam } else { 458185377Ssam /* convert to system clocks */ 459185377Ssam OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); 460185377Ssam ahp->ah_slottime = us; 461185377Ssam return AH_TRUE; 462185377Ssam } 463185377Ssam} 464185377Ssam 465185377Ssamu_int 466185377Ssamar5211GetSlotTime(struct ath_hal *ah) 467185377Ssam{ 468185377Ssam u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; 469185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 470185377Ssam} 471185377Ssam 472185377SsamHAL_BOOL 473185377Ssamar5211SetAckTimeout(struct ath_hal *ah, u_int us) 474185377Ssam{ 475185377Ssam struct ath_hal_5211 *ahp = AH5211(ah); 476185377Ssam 477185377Ssam if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { 478185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", 479185377Ssam __func__, us); 480185377Ssam ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ 481185377Ssam return AH_FALSE; 482185377Ssam } else { 483185377Ssam /* convert to system clocks */ 484185377Ssam OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 485185377Ssam AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); 486185377Ssam ahp->ah_acktimeout = us; 487185377Ssam return AH_TRUE; 488185377Ssam } 489185377Ssam} 490185377Ssam 491185377Ssamu_int 492185377Ssamar5211GetAckTimeout(struct ath_hal *ah) 493185377Ssam{ 494185377Ssam u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); 495185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 496185377Ssam} 497185377Ssam 498185377Ssamu_int 499185377Ssamar5211GetAckCTSRate(struct ath_hal *ah) 500185377Ssam{ 501185377Ssam return ((AH5211(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); 502185377Ssam} 503185377Ssam 504185377SsamHAL_BOOL 505185377Ssamar5211SetAckCTSRate(struct ath_hal *ah, u_int high) 506185377Ssam{ 507185377Ssam struct ath_hal_5211 *ahp = AH5211(ah); 508185377Ssam 509185377Ssam if (high) { 510185377Ssam OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 511185377Ssam ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; 512185377Ssam } else { 513185377Ssam OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 514185377Ssam ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; 515185377Ssam } 516185377Ssam return AH_TRUE; 517185377Ssam} 518185377Ssam 519185377SsamHAL_BOOL 520185377Ssamar5211SetCTSTimeout(struct ath_hal *ah, u_int us) 521185377Ssam{ 522185377Ssam struct ath_hal_5211 *ahp = AH5211(ah); 523185377Ssam 524185377Ssam if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { 525185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", 526185377Ssam __func__, us); 527185377Ssam ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ 528185377Ssam return AH_FALSE; 529185377Ssam } else { 530185377Ssam /* convert to system clocks */ 531185377Ssam OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 532185377Ssam AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); 533185377Ssam ahp->ah_ctstimeout = us; 534185377Ssam return AH_TRUE; 535185377Ssam } 536185377Ssam} 537185377Ssam 538185377Ssamu_int 539185377Ssamar5211GetCTSTimeout(struct ath_hal *ah) 540185377Ssam{ 541185377Ssam u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); 542185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 543185377Ssam} 544185377Ssam 545185377SsamHAL_BOOL 546185377Ssamar5211SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) 547185377Ssam{ 548185377Ssam /* nothing to do */ 549185377Ssam return AH_TRUE; 550185377Ssam} 551185377Ssam 552185377Ssamvoid 553185377Ssamar5211SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) 554185377Ssam{ 555185377Ssam} 556185377Ssam 557185377Ssam/* 558185377Ssam * Control Adaptive Noise Immunity Parameters 559185377Ssam */ 560185377SsamHAL_BOOL 561185377Ssamar5211AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) 562185377Ssam{ 563185377Ssam return AH_FALSE; 564185377Ssam} 565185377Ssam 566185377Ssamvoid 567187831Ssamar5211AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, 568187831Ssam const struct ieee80211_channel *chan) 569185377Ssam{ 570185377Ssam} 571185377Ssam 572185377Ssamvoid 573185377Ssamar5211MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) 574185377Ssam{ 575185377Ssam} 576185377Ssam 577185377Ssam/* 578185377Ssam * Get the rssi of frame curently being received. 579185377Ssam */ 580185377Ssamuint32_t 581185377Ssamar5211GetCurRssi(struct ath_hal *ah) 582185377Ssam{ 583185377Ssam return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); 584185377Ssam} 585185377Ssam 586185377Ssamu_int 587185377Ssamar5211GetDefAntenna(struct ath_hal *ah) 588185377Ssam{ 589185377Ssam return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); 590185377Ssam} 591185377Ssam 592185377Ssamvoid 593185377Ssamar5211SetDefAntenna(struct ath_hal *ah, u_int antenna) 594185377Ssam{ 595185377Ssam OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); 596185377Ssam} 597185377Ssam 598185377SsamHAL_ANT_SETTING 599185377Ssamar5211GetAntennaSwitch(struct ath_hal *ah) 600185377Ssam{ 601185377Ssam return AH5211(ah)->ah_diversityControl; 602185377Ssam} 603185377Ssam 604185377SsamHAL_BOOL 605185377Ssamar5211SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) 606185377Ssam{ 607187831Ssam const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 608185377Ssam 609185377Ssam if (chan == AH_NULL) { 610185377Ssam AH5211(ah)->ah_diversityControl = settings; 611185377Ssam return AH_TRUE; 612185377Ssam } 613185377Ssam return ar5211SetAntennaSwitchInternal(ah, settings, chan); 614185377Ssam} 615185377Ssam 616185377SsamHAL_STATUS 617185377Ssamar5211GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 618185377Ssam uint32_t capability, uint32_t *result) 619185377Ssam{ 620185377Ssam 621185377Ssam switch (type) { 622185377Ssam case HAL_CAP_CIPHER: /* cipher handled in hardware */ 623185377Ssam switch (capability) { 624185377Ssam case HAL_CIPHER_AES_OCB: 625185377Ssam case HAL_CIPHER_WEP: 626185377Ssam case HAL_CIPHER_CLR: 627185377Ssam return HAL_OK; 628185377Ssam default: 629185377Ssam return HAL_ENOTSUPP; 630185377Ssam } 631185377Ssam default: 632185377Ssam return ath_hal_getcapability(ah, type, capability, result); 633185377Ssam } 634185377Ssam} 635185377Ssam 636185377SsamHAL_BOOL 637185377Ssamar5211SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 638185377Ssam uint32_t capability, uint32_t setting, HAL_STATUS *status) 639185377Ssam{ 640185377Ssam switch (type) { 641185377Ssam case HAL_CAP_DIAG: /* hardware diagnostic support */ 642185377Ssam /* 643185377Ssam * NB: could split this up into virtual capabilities, 644185377Ssam * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly 645185377Ssam * seems worth the additional complexity. 646185377Ssam */ 647185377Ssam#ifdef AH_DEBUG 648185377Ssam AH_PRIVATE(ah)->ah_diagreg = setting; 649185377Ssam#else 650185377Ssam AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ 651185377Ssam#endif 652185377Ssam OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); 653185377Ssam return AH_TRUE; 654185377Ssam default: 655185377Ssam return ath_hal_setcapability(ah, type, capability, 656185377Ssam setting, status); 657185377Ssam } 658185377Ssam} 659185377Ssam 660185377SsamHAL_BOOL 661185377Ssamar5211GetDiagState(struct ath_hal *ah, int request, 662185377Ssam const void *args, uint32_t argsize, 663185377Ssam void **result, uint32_t *resultsize) 664185377Ssam{ 665185377Ssam struct ath_hal_5211 *ahp = AH5211(ah); 666185377Ssam 667185377Ssam (void) ahp; 668185377Ssam if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) 669185377Ssam return AH_TRUE; 670185377Ssam switch (request) { 671185377Ssam case HAL_DIAG_EEPROM: 672185377Ssam return ath_hal_eepromDiag(ah, request, 673185377Ssam args, argsize, result, resultsize); 674185377Ssam case HAL_DIAG_RFGAIN: 675185377Ssam *result = &ahp->ah_gainValues; 676185377Ssam *resultsize = sizeof(GAIN_VALUES); 677185377Ssam return AH_TRUE; 678185377Ssam case HAL_DIAG_RFGAIN_CURSTEP: 679185377Ssam *result = __DECONST(void *, ahp->ah_gainValues.currStep); 680185377Ssam *resultsize = (*result == AH_NULL) ? 681185377Ssam 0 : sizeof(GAIN_OPTIMIZATION_STEP); 682185377Ssam return AH_TRUE; 683185377Ssam } 684185377Ssam return AH_FALSE; 685185377Ssam} 686