1185377Ssam/* 2187831Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3185377Ssam * Copyright (c) 2002-2004 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 * 17187831Ssam * $FreeBSD$ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam 24185377Ssam#include "ar5210/ar5210.h" 25185377Ssam#include "ar5210/ar5210reg.h" 26185377Ssam#include "ar5210/ar5210phy.h" 27185377Ssam 28185380Ssam#include "ah_eeprom_v1.h" 29185380Ssam 30185377Ssam#define AR_NUM_GPIO 6 /* 6 GPIO bits */ 31185377Ssam#define AR_GPIOD_MASK 0x2f /* 6-bit mask */ 32185377Ssam 33185377Ssamvoid 34185377Ssamar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac) 35185377Ssam{ 36185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 37185377Ssam 38185377Ssam OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); 39185377Ssam} 40185377Ssam 41185377SsamHAL_BOOL 42185377Ssamar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac) 43185377Ssam{ 44185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 45185377Ssam 46185377Ssam OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); 47185377Ssam return AH_TRUE; 48185377Ssam} 49185377Ssam 50185377Ssamvoid 51185377Ssamar5210GetBssIdMask(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 59185377Ssamar5210SetBssIdMask(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 68185377Ssamar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) 69185377Ssam{ 70185377Ssam (void) OS_REG_READ(ah, AR_EP_AIR(off)); /* activate read op */ 71185377Ssam if (!ath_hal_wait(ah, AR_EP_STA, 72185377Ssam AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) { 73185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n", 74185377Ssam __func__, AR_EP_AIR(off)); 75185377Ssam return AH_FALSE; 76185377Ssam } 77185377Ssam *data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff; 78185377Ssam return AH_TRUE; 79185377Ssam} 80185377Ssam 81185380Ssam#ifdef AH_SUPPORT_WRITE_EEPROM 82185377Ssam/* 83185380Ssam * Write 16 bits of data to the specified EEPROM offset. 84185380Ssam */ 85185380SsamHAL_BOOL 86185380Ssamar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) 87185380Ssam{ 88185380Ssam return AH_FALSE; 89185380Ssam} 90185380Ssam#endif /* AH_SUPPORT_WRITE_EEPROM */ 91185380Ssam 92185380Ssam/* 93185380Ssam * Attempt to change the cards operating regulatory domain to the given value 94185380Ssam */ 95185380SsamHAL_BOOL 96185380Ssamar5210SetRegulatoryDomain(struct ath_hal *ah, 97185380Ssam uint16_t regDomain, HAL_STATUS *status) 98185380Ssam{ 99185380Ssam HAL_STATUS ecode; 100185380Ssam 101185380Ssam if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { 102185380Ssam ecode = HAL_EINVAL; 103185380Ssam goto bad; 104185380Ssam } 105185380Ssam /* 106185380Ssam * Check if EEPROM is configured to allow this; must 107185380Ssam * be a proper version and the protection bits must 108185380Ssam * permit re-writing that segment of the EEPROM. 109185380Ssam */ 110185380Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { 111185380Ssam ecode = HAL_EEWRITE; 112185380Ssam goto bad; 113185380Ssam } 114185380Ssam ecode = HAL_EIO; /* disallow all writes */ 115185380Ssambad: 116185380Ssam if (status) 117185380Ssam *status = ecode; 118185380Ssam return AH_FALSE; 119185380Ssam} 120185380Ssam 121185380Ssam/* 122185377Ssam * Return the wireless modes (a,b,g,t) supported by hardware. 123185377Ssam * 124185377Ssam * This value is what is actually supported by the hardware 125185377Ssam * and is unaffected by regulatory/country code settings. 126185377Ssam * 127185377Ssam */ 128185377Ssamu_int 129185377Ssamar5210GetWirelessModes(struct ath_hal *ah) 130185377Ssam{ 131185377Ssam /* XXX could enable turbo mode but can't do all rates */ 132185377Ssam return HAL_MODE_11A; 133185377Ssam} 134185377Ssam 135185377Ssam/* 136185377Ssam * Called if RfKill is supported (according to EEPROM). Set the interrupt and 137185377Ssam * GPIO values so the ISR and can disable RF on a switch signal 138185377Ssam */ 139185377Ssamvoid 140185377Ssamar5210EnableRfKill(struct ath_hal *ah) 141185377Ssam{ 142185377Ssam uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; 143185377Ssam int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); 144185377Ssam int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); 145185377Ssam 146185377Ssam /* 147185377Ssam * If radio disable switch connection to GPIO bit 0 is enabled 148185377Ssam * program GPIO interrupt. 149185377Ssam * If rfkill bit on eeprom is 1, setupeeprommap routine has already 150185377Ssam * verified that it is a later version of eeprom, it has a place for 151185377Ssam * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware 152185377Ssam * connection is present. 153185377Ssam */ 154185377Ssam ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity)); 155185377Ssam} 156185377Ssam 157185377Ssam/* 158185377Ssam * Configure GPIO Output lines 159185377Ssam */ 160185377SsamHAL_BOOL 161188974Ssamar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) 162185377Ssam{ 163185377Ssam HALASSERT(gpio < AR_NUM_GPIO); 164185377Ssam 165185377Ssam OS_REG_WRITE(ah, AR_GPIOCR, 166185377Ssam (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) 167185377Ssam | AR_GPIOCR_OUT1(gpio)); 168185377Ssam 169185377Ssam return AH_TRUE; 170185377Ssam} 171185377Ssam 172185377Ssam/* 173185377Ssam * Configure GPIO Input lines 174185377Ssam */ 175185377SsamHAL_BOOL 176185377Ssamar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio) 177185377Ssam{ 178185377Ssam HALASSERT(gpio < AR_NUM_GPIO); 179185377Ssam 180185377Ssam OS_REG_WRITE(ah, AR_GPIOCR, 181185377Ssam (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) 182185377Ssam | AR_GPIOCR_IN(gpio)); 183185377Ssam 184185377Ssam return AH_TRUE; 185185377Ssam} 186185377Ssam 187185377Ssam/* 188185377Ssam * Once configured for I/O - set output lines 189185377Ssam */ 190185377SsamHAL_BOOL 191185377Ssamar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) 192185377Ssam{ 193185377Ssam uint32_t reg; 194185377Ssam 195185377Ssam HALASSERT(gpio < AR_NUM_GPIO); 196185377Ssam 197185377Ssam reg = OS_REG_READ(ah, AR_GPIODO); 198185377Ssam reg &= ~(1 << gpio); 199185377Ssam reg |= (val&1) << gpio; 200185377Ssam 201185377Ssam OS_REG_WRITE(ah, AR_GPIODO, reg); 202185377Ssam return AH_TRUE; 203185377Ssam} 204185377Ssam 205185377Ssam/* 206185377Ssam * Once configured for I/O - get input lines 207185377Ssam */ 208185377Ssamuint32_t 209185377Ssamar5210GpioGet(struct ath_hal *ah, uint32_t gpio) 210185377Ssam{ 211185377Ssam if (gpio < AR_NUM_GPIO) { 212185377Ssam uint32_t val = OS_REG_READ(ah, AR_GPIODI); 213185377Ssam val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; 214185377Ssam return val; 215185377Ssam } else { 216185377Ssam return 0xffffffff; 217185377Ssam } 218185377Ssam} 219185377Ssam 220185377Ssam/* 221185377Ssam * Set the GPIO 0 Interrupt 222185377Ssam */ 223185377Ssamvoid 224185377Ssamar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) 225185377Ssam{ 226185377Ssam uint32_t val = OS_REG_READ(ah, AR_GPIOCR); 227185377Ssam 228185377Ssam /* Clear the bits that we will modify. */ 229185377Ssam val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | 230185377Ssam AR_GPIOCR_ALL(gpio)); 231185377Ssam 232185377Ssam val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA; 233185377Ssam if (ilevel) 234185377Ssam val |= AR_GPIOCR_INT_SELH; 235185377Ssam 236185377Ssam /* Don't need to change anything for low level interrupt. */ 237185377Ssam OS_REG_WRITE(ah, AR_GPIOCR, val); 238185377Ssam 239185377Ssam /* Change the interrupt mask. */ 240185377Ssam ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO); 241185377Ssam} 242185377Ssam 243185377Ssam/* 244185377Ssam * Change the LED blinking pattern to correspond to the connectivity 245185377Ssam */ 246185377Ssamvoid 247185377Ssamar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state) 248185377Ssam{ 249185377Ssam uint32_t val; 250185377Ssam 251185377Ssam val = OS_REG_READ(ah, AR_PCICFG); 252185377Ssam switch (state) { 253185377Ssam case HAL_LED_INIT: 254185377Ssam val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT); 255185377Ssam break; 256185377Ssam case HAL_LED_RUN: 257185377Ssam /* normal blink when connected */ 258185377Ssam val &= ~AR_PCICFG_LED_PEND; 259185377Ssam val |= AR_PCICFG_LED_ACT; 260185377Ssam break; 261185377Ssam default: 262185377Ssam val |= AR_PCICFG_LED_PEND; 263185377Ssam val &= ~AR_PCICFG_LED_ACT; 264185377Ssam break; 265185377Ssam } 266185377Ssam OS_REG_WRITE(ah, AR_PCICFG, val); 267185377Ssam} 268185377Ssam 269185377Ssam/* 270185377Ssam * Return 1 or 2 for the corresponding antenna that is in use 271185377Ssam */ 272185377Ssamu_int 273185377Ssamar5210GetDefAntenna(struct ath_hal *ah) 274185377Ssam{ 275185377Ssam uint32_t val = OS_REG_READ(ah, AR_STA_ID1); 276185377Ssam return (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1); 277185377Ssam} 278185377Ssam 279185377Ssamvoid 280185377Ssamar5210SetDefAntenna(struct ath_hal *ah, u_int antenna) 281185377Ssam{ 282185377Ssam uint32_t val = OS_REG_READ(ah, AR_STA_ID1); 283185377Ssam 284185377Ssam if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1)) { 285185377Ssam /* 286185377Ssam * Antenna change requested, force a toggle of the default. 287185377Ssam */ 288185377Ssam OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA); 289185377Ssam } 290185377Ssam} 291185377Ssam 292185377SsamHAL_ANT_SETTING 293185377Ssamar5210GetAntennaSwitch(struct ath_hal *ah) 294185377Ssam{ 295185377Ssam return HAL_ANT_VARIABLE; 296185377Ssam} 297185377Ssam 298185377SsamHAL_BOOL 299185377Ssamar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) 300185377Ssam{ 301185377Ssam /* XXX not sure how to fix antenna */ 302185377Ssam return (settings == HAL_ANT_VARIABLE); 303185377Ssam} 304185377Ssam 305185377Ssam/* 306185377Ssam * Change association related fields programmed into the hardware. 307185377Ssam * Writing a valid BSSID to the hardware effectively enables the hardware 308185377Ssam * to synchronize its TSF to the correct beacons and receive frames coming 309185377Ssam * from that BSSID. It is called by the SME JOIN operation. 310185377Ssam */ 311185377Ssamvoid 312185377Ssamar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) 313185377Ssam{ 314185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 315185377Ssam 316185377Ssam /* XXX save bssid for possible re-use on reset */ 317185377Ssam OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); 318185377Ssam OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); 319185377Ssam OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | 320185377Ssam ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S)); 321185377Ssam if (assocId == 0) 322185377Ssam OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL); 323185377Ssam else 324185377Ssam OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL); 325185377Ssam} 326185377Ssam 327185377Ssam/* 328185377Ssam * Get the current hardware tsf for stamlme. 329185377Ssam */ 330185377Ssamuint64_t 331185377Ssamar5210GetTsf64(struct ath_hal *ah) 332185377Ssam{ 333185377Ssam uint32_t low1, low2, u32; 334185377Ssam 335185377Ssam /* sync multi-word read */ 336185377Ssam low1 = OS_REG_READ(ah, AR_TSF_L32); 337185377Ssam u32 = OS_REG_READ(ah, AR_TSF_U32); 338185377Ssam low2 = OS_REG_READ(ah, AR_TSF_L32); 339185377Ssam if (low2 < low1) { /* roll over */ 340185377Ssam /* 341185377Ssam * If we are not preempted this will work. If we are 342185377Ssam * then we re-reading AR_TSF_U32 does no good as the 343185377Ssam * low bits will be meaningless. Likewise reading 344185377Ssam * L32, U32, U32, then comparing the last two reads 345185380Ssam * to check for rollover doesn't help if preempted--so 346185380Ssam * we take this approach as it costs one less PCI 347185380Ssam * read which can be noticeable when doing things 348185380Ssam * like timestamping packets in monitor mode. 349185377Ssam */ 350185377Ssam u32++; 351185377Ssam } 352185377Ssam return (((uint64_t) u32) << 32) | ((uint64_t) low2); 353185377Ssam} 354185377Ssam 355185377Ssam/* 356185377Ssam * Get the current hardware tsf for stamlme. 357185377Ssam */ 358185377Ssamuint32_t 359185377Ssamar5210GetTsf32(struct ath_hal *ah) 360185377Ssam{ 361185377Ssam return OS_REG_READ(ah, AR_TSF_L32); 362185377Ssam} 363185377Ssam 364185377Ssam/* 365185377Ssam * Reset the current hardware tsf for stamlme 366185377Ssam */ 367185377Ssamvoid 368185377Ssamar5210ResetTsf(struct ath_hal *ah) 369185377Ssam{ 370185377Ssam uint32_t val = OS_REG_READ(ah, AR_BEACON); 371185377Ssam 372185377Ssam OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); 373185377Ssam} 374185377Ssam 375185377Ssam/* 376185377Ssam * Grab a semi-random value from hardware registers - may not 377185377Ssam * change often 378185377Ssam */ 379185377Ssamuint32_t 380185377Ssamar5210GetRandomSeed(struct ath_hal *ah) 381185377Ssam{ 382185377Ssam uint32_t nf; 383185377Ssam 384185377Ssam nf = (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) >> 19) & 0x1ff; 385185377Ssam if (nf & 0x100) 386185377Ssam nf = 0 - ((nf ^ 0x1ff) + 1); 387185377Ssam return (OS_REG_READ(ah, AR_TSF_U32) ^ 388185377Ssam OS_REG_READ(ah, AR_TSF_L32) ^ nf); 389185377Ssam} 390185377Ssam 391185377Ssam/* 392185377Ssam * Detect if our card is present 393185377Ssam */ 394185377SsamHAL_BOOL 395185377Ssamar5210DetectCardPresent(struct ath_hal *ah) 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 return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff)); 403185377Ssam} 404185377Ssam 405185377Ssam/* 406185377Ssam * Update MIB Counters 407185377Ssam */ 408185377Ssamvoid 409185377Ssamar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) 410185377Ssam{ 411185377Ssam stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); 412185377Ssam stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); 413185377Ssam stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); 414185377Ssam stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); 415185377Ssam stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); 416185377Ssam} 417185377Ssam 418185377SsamHAL_BOOL 419185377Ssamar5210SetSifsTime(struct ath_hal *ah, u_int us) 420185377Ssam{ 421185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 422185377Ssam 423185377Ssam if (us > ath_hal_mac_usec(ah, 0x7ff)) { 424185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", 425185377Ssam __func__, us); 426185377Ssam ahp->ah_sifstime = (u_int) -1; /* restore default handling */ 427185377Ssam return AH_FALSE; 428185377Ssam } else { 429185377Ssam /* convert to system clocks */ 430185377Ssam OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS, 431185377Ssam ath_hal_mac_clks(ah, us)); 432185377Ssam ahp->ah_sifstime = us; 433185377Ssam return AH_TRUE; 434185377Ssam } 435185377Ssam} 436185377Ssam 437185377Ssamu_int 438185377Ssamar5210GetSifsTime(struct ath_hal *ah) 439185377Ssam{ 440185377Ssam u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff; 441185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 442185377Ssam} 443185377Ssam 444185377SsamHAL_BOOL 445185377Ssamar5210SetSlotTime(struct ath_hal *ah, u_int us) 446185377Ssam{ 447185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 448185377Ssam 449185377Ssam if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { 450185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", 451185377Ssam __func__, us); 452185377Ssam ahp->ah_slottime = (u_int) -1; /* restore default handling */ 453185377Ssam return AH_FALSE; 454185377Ssam } else { 455185377Ssam /* convert to system clocks */ 456185377Ssam OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us)); 457185377Ssam ahp->ah_slottime = us; 458185377Ssam return AH_TRUE; 459185377Ssam } 460185377Ssam} 461185377Ssam 462185377Ssamu_int 463185377Ssamar5210GetSlotTime(struct ath_hal *ah) 464185377Ssam{ 465185377Ssam u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff; 466185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 467185377Ssam} 468185377Ssam 469185377SsamHAL_BOOL 470185377Ssamar5210SetAckTimeout(struct ath_hal *ah, u_int us) 471185377Ssam{ 472185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 473185377Ssam 474185377Ssam if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { 475185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", 476185377Ssam __func__, us); 477185377Ssam ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ 478185377Ssam return AH_FALSE; 479185377Ssam } else { 480185377Ssam /* convert to system clocks */ 481185377Ssam OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 482185377Ssam AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); 483185377Ssam ahp->ah_acktimeout = us; 484185377Ssam return AH_TRUE; 485185377Ssam } 486185377Ssam} 487185377Ssam 488185377Ssamu_int 489185377Ssamar5210GetAckTimeout(struct ath_hal *ah) 490185377Ssam{ 491185377Ssam u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); 492185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 493185377Ssam} 494185377Ssam 495185377Ssamu_int 496185377Ssamar5210GetAckCTSRate(struct ath_hal *ah) 497185377Ssam{ 498185377Ssam return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); 499185377Ssam} 500185377Ssam 501185377SsamHAL_BOOL 502185377Ssamar5210SetAckCTSRate(struct ath_hal *ah, u_int high) 503185377Ssam{ 504185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 505185377Ssam 506185377Ssam if (high) { 507185377Ssam OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 508185377Ssam ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; 509185377Ssam } else { 510185377Ssam OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 511185377Ssam ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; 512185377Ssam } 513185377Ssam return AH_TRUE; 514185377Ssam} 515185377Ssam 516185377SsamHAL_BOOL 517185377Ssamar5210SetCTSTimeout(struct ath_hal *ah, u_int us) 518185377Ssam{ 519185377Ssam struct ath_hal_5210 *ahp = AH5210(ah); 520185377Ssam 521185377Ssam if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { 522185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", 523185377Ssam __func__, us); 524185377Ssam ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ 525185377Ssam return AH_FALSE; 526185377Ssam } else { 527185377Ssam /* convert to system clocks */ 528185377Ssam OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 529185377Ssam AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); 530185377Ssam ahp->ah_ctstimeout = us; 531185377Ssam return AH_TRUE; 532185377Ssam } 533185377Ssam} 534185377Ssam 535185377Ssamu_int 536185377Ssamar5210GetCTSTimeout(struct ath_hal *ah) 537185377Ssam{ 538185377Ssam u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); 539185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 540185377Ssam} 541185377Ssam 542185377SsamHAL_BOOL 543185377Ssamar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) 544185377Ssam{ 545185377Ssam /* nothing to do */ 546185377Ssam return AH_TRUE; 547185377Ssam} 548185377Ssam 549185377Ssamvoid 550185377Ssamar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) 551185377Ssam{ 552185377Ssam} 553185377Ssam 554185377Ssam/* 555185377Ssam * Control Adaptive Noise Immunity Parameters 556185377Ssam */ 557185377SsamHAL_BOOL 558185377Ssamar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) 559185377Ssam{ 560185377Ssam return AH_FALSE; 561185377Ssam} 562185377Ssam 563185377Ssamvoid 564217684Sadrianar5210RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats, 565187831Ssam const struct ieee80211_channel *chan) 566185377Ssam{ 567185377Ssam} 568185377Ssam 569185377Ssamvoid 570217684Sadrianar5210AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan) 571217684Sadrian{ 572217684Sadrian} 573217684Sadrian 574217684Sadrianvoid 575185377Ssamar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) 576185377Ssam{ 577185377Ssam} 578185377Ssam 579185377SsamHAL_STATUS 580185377Ssamar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 581185377Ssam uint32_t capability, uint32_t *result) 582185377Ssam{ 583185377Ssam 584185377Ssam switch (type) { 585185377Ssam case HAL_CAP_CIPHER: /* cipher handled in hardware */ 586243317Sadrian#if 0 587185377Ssam return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP); 588243317Sadrian#else 589243317Sadrian return HAL_ENOTSUPP; 590243317Sadrian#endif 591185377Ssam default: 592185377Ssam return ath_hal_getcapability(ah, type, capability, result); 593185377Ssam } 594185377Ssam} 595185377Ssam 596185377SsamHAL_BOOL 597185377Ssamar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 598185377Ssam uint32_t capability, uint32_t setting, HAL_STATUS *status) 599185377Ssam{ 600185377Ssam 601185377Ssam switch (type) { 602185377Ssam case HAL_CAP_DIAG: /* hardware diagnostic support */ 603185377Ssam /* 604185377Ssam * NB: could split this up into virtual capabilities, 605185377Ssam * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly 606185377Ssam * seems worth the additional complexity. 607185377Ssam */ 608185377Ssam#ifdef AH_DEBUG 609185377Ssam AH_PRIVATE(ah)->ah_diagreg = setting; 610185377Ssam#else 611185377Ssam AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ 612185377Ssam#endif 613243317Sadrian ar5210UpdateDiagReg(ah, AH_PRIVATE(ah)->ah_diagreg); 614185377Ssam return AH_TRUE; 615185377Ssam case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ 616185377Ssam return AH_FALSE; /* NB: disallow */ 617185377Ssam default: 618185377Ssam return ath_hal_setcapability(ah, type, capability, 619185377Ssam setting, status); 620185377Ssam } 621185377Ssam} 622185377Ssam 623185377SsamHAL_BOOL 624185377Ssamar5210GetDiagState(struct ath_hal *ah, int request, 625185377Ssam const void *args, uint32_t argsize, 626185377Ssam void **result, uint32_t *resultsize) 627185377Ssam{ 628185377Ssam#ifdef AH_PRIVATE_DIAG 629185377Ssam uint32_t pcicfg; 630185377Ssam HAL_BOOL ok; 631185377Ssam 632185377Ssam switch (request) { 633185377Ssam case HAL_DIAG_EEPROM: 634185377Ssam /* XXX */ 635185377Ssam break; 636185377Ssam case HAL_DIAG_EEREAD: 637185377Ssam if (argsize != sizeof(uint16_t)) 638185377Ssam return AH_FALSE; 639185377Ssam pcicfg = OS_REG_READ(ah, AR_PCICFG); 640185377Ssam OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL); 641185377Ssam ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result); 642185377Ssam OS_REG_WRITE(ah, AR_PCICFG, pcicfg); 643185377Ssam if (ok) 644185377Ssam *resultsize = sizeof(uint16_t); 645185377Ssam return ok; 646185377Ssam } 647185377Ssam#endif 648185377Ssam return ath_hal_getdiagstate(ah, request, 649185377Ssam args, argsize, result, resultsize); 650185377Ssam} 651234873Sadrian 652234873Sadrian/* 653234873Sadrian * Return what percentage of the extension channel is busy. 654234873Sadrian * This is always disabled for AR5210 series NICs. 655234873Sadrian */ 656234873Sadrianuint32_t 657234873Sadrianar5210Get11nExtBusy(struct ath_hal *ah) 658234873Sadrian{ 659234873Sadrian 660234873Sadrian return (0); 661234873Sadrian} 662234873Sadrian 663234873Sadrian/* 664234873Sadrian * There's no channel survey support for the AR5210. 665234873Sadrian */ 666234873SadrianHAL_BOOL 667234873Sadrianar5210GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) 668234873Sadrian{ 669234873Sadrian 670234873Sadrian return (AH_FALSE); 671234873Sadrian} 672235206Sadrian 673235206Sadrianvoid 674247286Sadrianar5210SetChainMasks(struct ath_hal *ah, uint32_t txchainmask, 675247286Sadrian uint32_t rxchainmask) 676247286Sadrian{ 677247286Sadrian} 678247286Sadrian 679247286Sadrianvoid 680235206Sadrianar5210EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 681235206Sadrian{ 682235206Sadrian} 683235206Sadrian 684235206Sadrianvoid 685235206Sadrianar5210GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 686235206Sadrian{ 687235206Sadrian} 688243317Sadrian 689243317Sadrian/* 690243317Sadrian * Update the diagnostic register. 691243317Sadrian * 692243317Sadrian * This merges in the diagnostic register setting with the default 693243317Sadrian * value, which may or may not involve disabling hardware encryption. 694243317Sadrian */ 695243317Sadrianvoid 696243317Sadrianar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val) 697243317Sadrian{ 698243317Sadrian 699243317Sadrian /* Disable all hardware encryption */ 700243317Sadrian val |= AR_DIAG_SW_DIS_CRYPTO; 701243317Sadrian OS_REG_WRITE(ah, AR_DIAG_SW, val); 702243317Sadrian} 703