diff options
-rw-r--r-- | sys/conf/files | 4 | ||||
-rw-r--r-- | sys/dev/ic/ar5212.c | 2822 | ||||
-rw-r--r-- | sys/dev/ic/ar5212reg.h | 1210 | ||||
-rw-r--r-- | sys/dev/ic/ar5212var.h | 915 | ||||
-rw-r--r-- | sys/dev/ic/ar5xxx.c | 17 |
5 files changed, 4961 insertions, 7 deletions
diff --git a/sys/conf/files b/sys/conf/files index 7d73c964650..e80bdd4da1c 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.327 2005/02/15 20:51:16 damien Exp $ +# $OpenBSD: files,v 1.328 2005/02/19 16:58:00 reyk Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -331,7 +331,7 @@ define ar5xxx file dev/ic/ar5xxx.c ar5xxx file dev/ic/ar5210.c ar5xxx #file dev/ic/ar5211.c ar5xxx -#file dev/ic/ar5212.c ar5xxx +file dev/ic/ar5212.c ar5xxx # Atheros AR5k (802.11/a/b/g) driver device ath: ether, ifnet, ifmedia, ar5xxx, wlan, gpiobus diff --git a/sys/dev/ic/ar5212.c b/sys/dev/ic/ar5212.c new file mode 100644 index 00000000000..34092d30296 --- /dev/null +++ b/sys/dev/ic/ar5212.c @@ -0,0 +1,2822 @@ +/* $OpenBSD: ar5212.c,v 1.1 2005/02/19 16:58:00 reyk Exp $ */ + +/* + * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * HAL interface for the Atheros AR5001 Wireless LAN chipset + * (AR5212 + AR5111/AR5112). + */ + +#include <dev/ic/ar5xxx.h> +#include <dev/ic/ar5212reg.h> +#include <dev/ic/ar5212var.h> + +HAL_BOOL ar5k_ar5212_nic_reset(struct ath_hal *, u_int32_t); +HAL_BOOL ar5k_ar5212_nic_wakeup(struct ath_hal *, u_int16_t); +u_int16_t ar5k_ar5212_radio_revision(struct ath_hal *, HAL_CHIP); +const void ar5k_ar5212_fill(struct ath_hal *); +HAL_BOOL ar5k_ar5212_txpower(struct ath_hal *, HAL_CHANNEL *, u_int); + +/* + * Initial register setting for the AR5212 + */ +static const struct ar5k_ar5212_ini ar5212_ini[] = + AR5K_AR5212_INI; +static const struct ar5k_ar5212_ini_mode ar5212_mode[] = + AR5K_AR5212_INI_MODE; +static const struct ar5k_ar5212_ini_rfgain ar5212_rfgain[] = + AR5K_AR5212_INI_RFGAIN; + +AR5K_HAL_FUNCTIONS(extern, ar5k_ar5212,); + +const void +ar5k_ar5212_fill(hal) + struct ath_hal *hal; +{ + hal->ah_magic = AR5K_AR5212_MAGIC; + + /* + * Init/Exit functions + */ + AR5K_HAL_FUNCTION(hal, ar5212, getRateTable); + AR5K_HAL_FUNCTION(hal, ar5212, detach); + + /* + * Reset functions + */ + AR5K_HAL_FUNCTION(hal, ar5212, reset); + AR5K_HAL_FUNCTION(hal, ar5212, setPCUConfig); + AR5K_HAL_FUNCTION(hal, ar5212, perCalibration); + + /* + * TX functions + */ + AR5K_HAL_FUNCTION(hal, ar5212, updateTxTrigLevel); + AR5K_HAL_FUNCTION(hal, ar5212, setupTxQueue); + AR5K_HAL_FUNCTION(hal, ar5212, setTxQueueProps); + AR5K_HAL_FUNCTION(hal, ar5212, releaseTxQueue); + AR5K_HAL_FUNCTION(hal, ar5212, resetTxQueue); + AR5K_HAL_FUNCTION(hal, ar5212, getTxDP); + AR5K_HAL_FUNCTION(hal, ar5212, setTxDP); + AR5K_HAL_FUNCTION(hal, ar5212, startTxDma); + AR5K_HAL_FUNCTION(hal, ar5212, stopTxDma); + AR5K_HAL_FUNCTION(hal, ar5212, setupTxDesc); + AR5K_HAL_FUNCTION(hal, ar5212, setupXTxDesc); + AR5K_HAL_FUNCTION(hal, ar5212, fillTxDesc); + AR5K_HAL_FUNCTION(hal, ar5212, procTxDesc); + AR5K_HAL_FUNCTION(hal, ar5212, hasVEOL); + + /* + * RX functions + */ + AR5K_HAL_FUNCTION(hal, ar5212, getRxDP); + AR5K_HAL_FUNCTION(hal, ar5212, setRxDP); + AR5K_HAL_FUNCTION(hal, ar5212, enableReceive); + AR5K_HAL_FUNCTION(hal, ar5212, stopDmaReceive); + AR5K_HAL_FUNCTION(hal, ar5212, startPcuReceive); + AR5K_HAL_FUNCTION(hal, ar5212, stopPcuReceive); + AR5K_HAL_FUNCTION(hal, ar5212, setMulticastFilter); + AR5K_HAL_FUNCTION(hal, ar5212, setMulticastFilterIndex); + AR5K_HAL_FUNCTION(hal, ar5212, clrMulticastFilterIndex); + AR5K_HAL_FUNCTION(hal, ar5212, getRxFilter); + AR5K_HAL_FUNCTION(hal, ar5212, setRxFilter); + AR5K_HAL_FUNCTION(hal, ar5212, setupRxDesc); + AR5K_HAL_FUNCTION(hal, ar5212, procRxDesc); + AR5K_HAL_FUNCTION(hal, ar5212, rxMonitor); + + /* + * Misc functions + */ + AR5K_HAL_FUNCTION(hal, ar5212, dumpState); + AR5K_HAL_FUNCTION(hal, ar5212, getDiagState); + AR5K_HAL_FUNCTION(hal, ar5212, getMacAddress); + AR5K_HAL_FUNCTION(hal, ar5212, setMacAddress); + AR5K_HAL_FUNCTION(hal, ar5212, setRegulatoryDomain); + AR5K_HAL_FUNCTION(hal, ar5212, setLedState); + AR5K_HAL_FUNCTION(hal, ar5212, writeAssocid); + AR5K_HAL_FUNCTION(hal, ar5212, gpioCfgInput); + AR5K_HAL_FUNCTION(hal, ar5212, gpioCfgOutput); + AR5K_HAL_FUNCTION(hal, ar5212, gpioGet); + AR5K_HAL_FUNCTION(hal, ar5212, gpioSet); + AR5K_HAL_FUNCTION(hal, ar5212, gpioSetIntr); + AR5K_HAL_FUNCTION(hal, ar5212, getTsf32); + AR5K_HAL_FUNCTION(hal, ar5212, getTsf64); + AR5K_HAL_FUNCTION(hal, ar5212, resetTsf); + AR5K_HAL_FUNCTION(hal, ar5212, getRegDomain); + AR5K_HAL_FUNCTION(hal, ar5212, detectCardPresent); + AR5K_HAL_FUNCTION(hal, ar5212, updateMibCounters); + AR5K_HAL_FUNCTION(hal, ar5212, getRfGain); + AR5K_HAL_FUNCTION(hal, ar5212, setSlotTime); + AR5K_HAL_FUNCTION(hal, ar5212, getSlotTime); + AR5K_HAL_FUNCTION(hal, ar5212, setAckTimeout); + AR5K_HAL_FUNCTION(hal, ar5212, getAckTimeout); + AR5K_HAL_FUNCTION(hal, ar5212, setCTSTimeout); + AR5K_HAL_FUNCTION(hal, ar5212, getCTSTimeout); + + /* + * Key table (WEP) functions + */ + AR5K_HAL_FUNCTION(hal, ar5212, isHwCipherSupported); + AR5K_HAL_FUNCTION(hal, ar5212, getKeyCacheSize); + AR5K_HAL_FUNCTION(hal, ar5212, resetKeyCacheEntry); + AR5K_HAL_FUNCTION(hal, ar5212, isKeyCacheEntryValid); + AR5K_HAL_FUNCTION(hal, ar5212, setKeyCacheEntry); + AR5K_HAL_FUNCTION(hal, ar5212, setKeyCacheEntryMac); + + /* + * Power management functions + */ + AR5K_HAL_FUNCTION(hal, ar5212, setPowerMode); + AR5K_HAL_FUNCTION(hal, ar5212, getPowerMode); + AR5K_HAL_FUNCTION(hal, ar5212, queryPSPollSupport); + AR5K_HAL_FUNCTION(hal, ar5212, initPSPoll); + AR5K_HAL_FUNCTION(hal, ar5212, enablePSPoll); + AR5K_HAL_FUNCTION(hal, ar5212, disablePSPoll); + + /* + * Beacon functions + */ + AR5K_HAL_FUNCTION(hal, ar5212, beaconInit); + AR5K_HAL_FUNCTION(hal, ar5212, setStationBeaconTimers); + AR5K_HAL_FUNCTION(hal, ar5212, resetStationBeaconTimers); + AR5K_HAL_FUNCTION(hal, ar5212, waitForBeaconDone); + + /* + * Interrupt functions + */ + AR5K_HAL_FUNCTION(hal, ar5212, isInterruptPending); + AR5K_HAL_FUNCTION(hal, ar5212, getPendingInterrupts); + AR5K_HAL_FUNCTION(hal, ar5212, getInterrupts); + AR5K_HAL_FUNCTION(hal, ar5212, setInterrupts); + + /* + * Chipset functions (ar5k-specific, non-HAL) + */ + AR5K_HAL_FUNCTION(hal, ar5212, get_capabilities); + AR5K_HAL_FUNCTION(hal, ar5212, radar_alert); + + /* + * EEPROM access + */ + AR5K_HAL_FUNCTION(hal, ar5212, eeprom_is_busy); + AR5K_HAL_FUNCTION(hal, ar5212, eeprom_read); + AR5K_HAL_FUNCTION(hal, ar5212, eeprom_write); +} + +struct ath_hal * +ar5k_ar5212_attach(device, sc, st, sh, status) + u_int16_t device; + void *sc; + bus_space_tag_t st; + bus_space_handle_t sh; + int *status; +{ + struct ath_hal *hal = (struct ath_hal*) sc; + u_int8_t mac[IEEE80211_ADDR_LEN]; + u_int32_t srev; + + ar5k_ar5212_fill(hal); + + /* Bring device out of sleep and reset it's units */ + if (ar5k_ar5212_nic_wakeup(hal, AR5K_INIT_MODE) != AH_TRUE) + return (NULL); + + /* Get MAC, PHY and RADIO revisions */ + srev = AR5K_REG_READ(AR5K_AR5212_SREV) & AR5K_AR5212_SREV_M; + hal->ah_mac_version = srev & AR5K_AR5212_SREV_VERSION; + hal->ah_mac_revision = srev & AR5K_AR5212_SREV_REVISION; + hal->ah_phy_revision = AR5K_REG_READ(AR5K_AR5212_PHY_CHIP_ID) & + 0x00ffffffff; + + hal->ah_radio_5ghz_revision = + ar5k_ar5212_radio_revision(hal, HAL_CHIP_5GHZ); + + /* Get the 2GHz radio revision if it's supported */ + if (hal->ah_mac_version >= AR5K_SREV_VER_AR5211) + hal->ah_radio_2ghz_revision = + ar5k_ar5212_radio_revision(hal, HAL_CHIP_2GHZ); + + /* Identify the chipset (this has to be done in an early step) */ + hal->ah_version = AR5K_AR5212; + hal->ah_radio = hal->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112 ? + AR5K_AR5111 : AR5K_AR5112; + hal->ah_phy = AR5K_AR5212_PHY(0); + + memset(&mac, 0xff, sizeof(mac)); + ar5k_ar5212_writeAssocid(hal, mac, 0, 0); + ar5k_ar5212_getMacAddress(hal, mac); + ar5k_ar5212_setPCUConfig(hal); + + return (hal); +} + +HAL_BOOL +ar5k_ar5212_nic_reset(hal, val) + struct ath_hal *hal; + u_int32_t val; +{ + HAL_BOOL ret = AH_FALSE; + u_int32_t mask = val ? val : ~0; + + /* Read-and-clear */ + AR5K_REG_READ(AR5K_AR5212_RXDP); + + /* + * Reset the device and wait until success + */ + AR5K_REG_WRITE(AR5K_AR5212_RC, val); + + /* Wait at least 128 PCI clocks */ + AR5K_DELAY(15); + + val &= + AR5K_AR5212_RC_PCU | AR5K_AR5212_RC_BB; + + mask &= + AR5K_AR5212_RC_PCU | AR5K_AR5212_RC_BB; + + ret = ar5k_register_timeout(hal, AR5K_AR5212_RC, mask, val, AH_FALSE); + + /* + * Reset configuration register + */ + if ((val & AR5K_AR5212_RC_PCU) == 0) + AR5K_REG_WRITE(AR5K_AR5212_CFG, AR5K_AR5212_INIT_CFG); + + return (ret); +} + +HAL_BOOL +ar5k_ar5212_nic_wakeup(hal, flags) + struct ath_hal *hal; + u_int16_t flags; +{ + u_int32_t turbo, mode, clock; + + turbo = 0; + mode = 0; + clock = 0; + + /* + * Get channel mode flags + */ + + if (hal->ah_radio >= AR5K_AR5112) { + mode = AR5K_AR5212_PHY_MODE_RAD_AR5112; + clock = AR5K_AR5212_PHY_PLL_AR5112; + } else { + mode = AR5K_AR5212_PHY_MODE_RAD_AR5111; + clock = AR5K_AR5212_PHY_PLL_AR5111; + } + + if (flags & IEEE80211_CHAN_2GHZ) { + mode |= AR5K_AR5212_PHY_MODE_FREQ_2GHZ; + clock |= AR5K_AR5212_PHY_PLL_44MHZ; + } else if (flags & IEEE80211_CHAN_5GHZ) { + mode |= AR5K_AR5212_PHY_MODE_FREQ_5GHZ; + clock |= AR5K_AR5212_PHY_PLL_40MHZ; + } else { + AR5K_PRINT("invalid radio frequency mode\n"); + return (AH_FALSE); + } + + if (flags & IEEE80211_CHAN_CCK) { + mode |= AR5K_AR5212_PHY_MODE_MOD_CCK; + } else if (flags & IEEE80211_CHAN_OFDM) { + mode |= AR5K_AR5212_PHY_MODE_MOD_OFDM; + } else if (flags & IEEE80211_CHAN_DYN) { + mode |= AR5K_AR5212_PHY_MODE_MOD_DYN; + } else { + AR5K_PRINT("invalid radio frequency mode\n"); + return (AH_FALSE); + } + + if (flags & IEEE80211_CHAN_TURBO) { + turbo = AR5K_AR5212_PHY_TURBO_MODE | + AR5K_AR5212_PHY_TURBO_SHORT; + } + + /* + * Reset and wakeup the device + */ + + /* ...reset chipset and PCI device */ + if (ar5k_ar5212_nic_reset(hal, + AR5K_AR5212_RC_CHIP | AR5K_AR5212_RC_PCI) == AH_FALSE) { + AR5K_PRINT("failed to reset the AR5212 + PCI chipset\n"); + return (AH_FALSE); + } + + /* ...wakeup */ + if (ar5k_ar5212_setPowerMode(hal, + HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) { + AR5K_PRINT("failed to resume the AR5212 (again)\n"); + return (AH_FALSE); + } + + /* ...final warm reset */ + if (ar5k_ar5212_nic_reset(hal, 0) == AH_FALSE) { + AR5K_PRINT("failed to warm reset the AR5212\n"); + return (AH_FALSE); + } + + /* ...set the PHY operating mode */ + AR5K_REG_WRITE(AR5K_AR5212_PHY_PLL, clock); + AR5K_DELAY(300); + + AR5K_REG_WRITE(AR5K_AR5212_PHY_MODE, mode); + AR5K_REG_WRITE(AR5K_AR5212_PHY_TURBO, turbo); + + return (AH_TRUE); +} + +u_int16_t +ar5k_ar5212_radio_revision(hal, chip) + struct ath_hal *hal; + HAL_CHIP chip; +{ + int i; + u_int32_t srev; + u_int16_t ret; + + /* + * Set the radio chip access register + */ + switch (chip) { + case HAL_CHIP_2GHZ: + AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_2GHZ); + break; + case HAL_CHIP_5GHZ: + AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_5GHZ); + break; + default: + return (0); + } + + AR5K_DELAY(2000); + + /* ...wait until PHY is ready and read the selected radio revision */ + AR5K_REG_WRITE(AR5K_AR5212_PHY(0x34), 0x00001c16); + + for (i = 0; i < 8; i++) + AR5K_REG_WRITE(AR5K_AR5212_PHY(0x20), 0x00010000); + srev = (AR5K_REG_READ(AR5K_AR5212_PHY(0x100)) >> 24) & 0xff; + + ret = ar5k_bitswap(((srev & 0xf0) >> 4) | ((srev & 0x0f) << 4), 8); + + /* Reset to the 5GHz mode */ + AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_5GHZ); + + return (ret); +} + +const HAL_RATE_TABLE * +ar5k_ar5212_getRateTable(hal, mode) + struct ath_hal *hal; + u_int mode; +{ + switch (mode) { + case HAL_MODE_11A: + return (&hal->ah_rt_11a); + case HAL_MODE_TURBO: + return (&hal->ah_rt_turbo); + case HAL_MODE_11B: + return (&hal->ah_rt_11b); + case HAL_MODE_11G: + case HAL_MODE_PUREG: + return (&hal->ah_rt_11g); + default: + return (NULL); + } + + return (NULL); +} + +void +ar5k_ar5212_detach(hal) + struct ath_hal *hal; +{ + /* + * Free HAL structure, assume interrupts are down + */ + free(hal, M_DEVBUF); +} + +HAL_BOOL +ar5k_ar5212_reset(hal, op_mode, channel, change_channel, status) + struct ath_hal *hal; + HAL_OPMODE op_mode; + HAL_CHANNEL *channel; + HAL_BOOL change_channel; + HAL_STATUS *status; +{ + struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom; + u_int8_t mac[IEEE80211_ADDR_LEN]; + u_int32_t data; + u_int i, phy, mode, freq, ee_mode, ant[2]; + HAL_BOOL ar5112; + + if (ar5k_ar5212_nic_wakeup(hal, channel->c_channel_flags) == AH_FALSE) + return (AH_FALSE); + + /* + * Initialize operating mode + */ + hal->ah_op_mode = op_mode; + + ar5112 = hal->ah_radio >= AR5K_AR5112 ? AH_TRUE : AH_FALSE; + + if (channel->c_channel_flags & IEEE80211_CHAN_A) { + mode = AR5K_INI_VAL_11A; + freq = AR5K_INI_RFGAIN_5GHZ; + ee_mode = AR5K_EEPROM_MODE_11A; + } else if (channel->c_channel_flags & IEEE80211_CHAN_T) { + mode = AR5K_INI_VAL_11A_TURBO; + freq = AR5K_INI_RFGAIN_5GHZ; + ee_mode = AR5K_EEPROM_MODE_11A; + } else if (channel->c_channel_flags & IEEE80211_CHAN_B) { + mode = AR5K_INI_VAL_11B; + freq = AR5K_INI_RFGAIN_2GHZ; + ee_mode = AR5K_EEPROM_MODE_11B; + } else if (channel->c_channel_flags & IEEE80211_CHAN_G) { + mode = AR5K_INI_VAL_11G; + freq = AR5K_INI_RFGAIN_2GHZ; + ee_mode = AR5K_EEPROM_MODE_11G; + } else if (channel->c_channel_flags & CHANNEL_TG) { + mode = AR5K_INI_VAL_11G_TURBO; + freq = AR5K_INI_RFGAIN_2GHZ; + ee_mode = AR5K_EEPROM_MODE_11G; + } else if (channel->c_channel_flags & CHANNEL_XR) { + mode = AR5K_INI_VAL_XR; + freq = AR5K_INI_RFGAIN_5GHZ; + ee_mode = AR5K_EEPROM_MODE_11A; + } else { + AR5K_PRINTF("invalid channel: %d\n", channel->c_channel); + return (AH_FALSE); + } + + /* PHY access enable */ + AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_5GHZ); + + /* + * Write initial register settings + */ + for (i = 0; i < AR5K_ELEMENTS(ar5212_ini); i++) { + if (change_channel == AH_TRUE && + ar5212_ini[i].ini_register >= AR5K_AR5212_PCU_MIN && + ar5212_ini[i].ini_register <= AR5K_AR5212_PCU_MAX) + continue; + + if (ar5112 == AH_TRUE) { + if (!(ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5112)) + continue; + } else { + if (!(ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5111)) + continue; + } + + AR5K_REG_WRITE((u_int32_t)ar5212_ini[i].ini_register, + ar5212_ini[i].ini_value); + } + + /* + * Write initial mode settings + */ + for (i = 0; i < AR5K_ELEMENTS(ar5212_mode); i++) { + if (ar5212_mode[i].mode_flags == AR5K_INI_FLAG_511X) + phy = AR5K_INI_PHY_511X; + else if (ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5111 && + ar5112 == AH_FALSE) + phy = AR5K_INI_PHY_5111; + else if (ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5112 && + ar5112 == AH_TRUE) + phy = AR5K_INI_PHY_5112; + else + continue; + + AR5K_REG_WRITE((u_int32_t)ar5212_mode[i].mode_register, + ar5212_mode[i].mode_value[phy][mode]); + } + + /* + * Write initial RF gain settings + */ + phy = ar5112 == AH_TRUE ? AR5K_INI_PHY_5112 : AR5K_INI_PHY_5111; + for (i = 0; i < AR5K_ELEMENTS(ar5212_rfgain); i++) + AR5K_REG_WRITE((u_int32_t)ar5212_rfgain[i].rfg_register, + ar5212_rfgain[i].rfg_value[phy][freq]); + + AR5K_DELAY(1000); + + /* + * Set TX power + */ + if (ar5k_ar5212_txpower(hal, channel, + hal->ah_txpower.txp_max) == AH_FALSE) + return (AH_FALSE); + + /* + * Write RF registers + */ + if (ar5k_rfregs(hal, channel, mode) == AH_FALSE) + return (AH_FALSE); + + /* + * Configure additional registers + */ + + /* OFDM timings */ + if (channel->c_channel_flags & IEEE80211_CHAN_OFDM) { + u_int32_t coef_scaled, coef_exp, coef_man, ds_coef_exp, + ds_coef_man, clock; + + clock = channel->c_channel_flags & IEEE80211_CHAN_T ? 80 : 40; + coef_scaled = ((5 * (clock << 24)) / 2) / channel->c_channel; + + for (coef_exp = 31; coef_exp > 0; coef_exp--) + if ((coef_scaled >> coef_exp) & 0x1) + break; + + if (!coef_exp) + return (AH_FALSE); + + coef_exp = 14 - (coef_exp - 24); + coef_man = coef_scaled + (1 << (24 - coef_exp - 1)); + ds_coef_man = coef_man >> (24 - coef_exp); + ds_coef_exp = coef_exp - 16; + + AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_TIMING_3, + AR5K_AR5212_PHY_TIMING_3_DSC_MAN, ds_coef_man); + AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_TIMING_3, + AR5K_AR5212_PHY_TIMING_3_DSC_EXP, ds_coef_exp); + } + + /* Set antenna mode */ + AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x44), + hal->ah_antenna[ee_mode][0], 0xfffffc06); + + ant[0] = HAL_ANT_FIXED_A; + ant[1] = HAL_ANT_FIXED_B; + + if (hal->ah_ant_diversity == AH_FALSE) { + if (freq == AR5K_INI_RFGAIN_2GHZ) + ant[0] = HAL_ANT_FIXED_B; + else if (freq == AR5K_INI_RFGAIN_5GHZ) + ant[1] = HAL_ANT_FIXED_A; + } + + AR5K_REG_WRITE(AR5K_AR5212_PHY_ANT_SWITCH_TABLE_0, + hal->ah_antenna[ee_mode][ant[0]]); + AR5K_REG_WRITE(AR5K_AR5212_PHY_ANT_SWITCH_TABLE_1, + hal->ah_antenna[ee_mode][ant[1]]); + + /* Commit values from EEPROM */ + if (ar5112 == AH_FALSE) + AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_FC, + AR5K_AR5212_PHY_FC_TX_CLIP, ee->ee_tx_clip); + + AR5K_REG_WRITE(AR5K_AR5212_PHY(0x5a), + AR5K_AR5212_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode])); + + AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x11), + (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, 0xffffc07f); + AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x12), + (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, 0xfffc0fff); + AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x14), + (ee->ee_adc_desired_size[ee_mode] & 0x00ff) | + ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00), 0xffff0000); + + AR5K_REG_WRITE(AR5K_AR5212_PHY(0x0d), + (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | + (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | + (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | + (ee->ee_tx_frm2xpa_enable[ee_mode])); + + AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x0a), + ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff); + AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x19), + (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff); + AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x49), 4, 0xffffff01); + + AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_IQ, + AR5K_AR5212_PHY_IQ_CORR_ENABLE | + (ee->ee_i_cal[ee_mode] << AR5K_AR5212_PHY_IQ_CORR_Q_I_COFF_S) | + ee->ee_q_cal[ee_mode]); + + if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) { + AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_GAIN_2GHZ, + AR5K_AR5212_PHY_GAIN_2GHZ_MARGIN_TXRX, + ee->ee_margin_tx_rx[ee_mode]); + } + + /* Misc */ + memset(&mac, 0xff, sizeof(mac)); + ar5k_ar5212_writeAssocid(hal, mac, 0, 0); + ar5k_ar5212_setPCUConfig(hal); + AR5K_REG_WRITE(AR5K_AR5212_PISR, 0xffffffff); + AR5K_REG_WRITE(AR5K_AR5212_RSSI_THR, AR5K_TUNE_RSSI_THRES); + + /* + * Set channel and calibrate the PHY + */ + if (ar5k_channel(hal, channel) == AH_FALSE) + return (AH_FALSE); + + /* + * Enable the PHY and wait until completion + */ + AR5K_REG_WRITE(AR5K_AR5212_PHY_ACTIVE, AR5K_AR5212_PHY_ENABLE); + + data = AR5K_REG_READ(AR5K_AR5212_PHY_RX_DELAY) & + AR5K_AR5212_PHY_RX_DELAY_M; + data = (channel->c_channel_flags & IEEE80211_CHAN_CCK) ? + ((data << 2) / 22) : (data / 10); + + AR5K_DELAY(100 + data); + + /* + * Start calibration + */ + AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_AGCCTL, + AR5K_AR5212_PHY_AGCCTL_NF | + AR5K_AR5212_PHY_AGCCTL_CAL); + + if (channel->c_channel_flags & IEEE80211_CHAN_B) { + hal->ah_calibration = AH_FALSE; + } else { + hal->ah_calibration = AH_TRUE; + AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_IQ, + AR5K_AR5212_PHY_IQ_CAL_NUM_LOG_MAX, 15); + AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_IQ, + AR5K_AR5212_PHY_IQ_RUN); + } + + /* + * Reset queues and start beacon timers at the end of the reset routine + */ + for (i = 0; i < hal->ah_capabilities.cap_queues.q_tx_num; i++) { + AR5K_REG_WRITE_Q(AR5K_AR5212_DCU_QCUMASK(i), i); + if (ar5k_ar5212_resetTxQueue(hal, i) == AH_FALSE) { + AR5K_PRINTF("failed to reset TX queue #%d\n", i); + return (AH_FALSE); + } + } + + /* Pre-enable interrupts */ + ar5k_ar5212_setInterrupts(hal, HAL_INT_RX | HAL_INT_TX | HAL_INT_FATAL); + + /* + * Set RF kill flags if supported by the device (read from the EEPROM) + */ + if (AR5K_EEPROM_HDR_RFKILL(hal->ah_capabilities.cap_eeprom.ee_header)) { + ar5k_ar5212_gpioCfgInput(hal, 0); + if ((hal->ah_gpio[0] = ar5k_ar5212_gpioGet(hal, 0)) == 0) + ar5k_ar5212_gpioSetIntr(hal, 0, 1); + else + ar5k_ar5212_gpioSetIntr(hal, 0, 0); + } + + /* + * Set the 32MHz reference clock + */ + AR5K_REG_WRITE(AR5K_AR5212_PHY_SCR, AR5K_AR5212_PHY_SCR_32MHZ); + AR5K_REG_WRITE(AR5K_AR5212_PHY_SLMT, AR5K_AR5212_PHY_SLMT_32MHZ); + AR5K_REG_WRITE(AR5K_AR5212_PHY_SCAL, AR5K_AR5212_PHY_SCAL_32MHZ); + AR5K_REG_WRITE(AR5K_AR5212_PHY_SCLOCK, AR5K_AR5212_PHY_SCLOCK_32MHZ); + AR5K_REG_WRITE(AR5K_AR5212_PHY_SDELAY, AR5K_AR5212_PHY_SDELAY_32MHZ); + AR5K_REG_WRITE(AR5K_AR5212_PHY_SPENDING, hal->ah_radio == AR5K_AR5111 ? + AR5K_AR5212_PHY_SPENDING_AR5111 : AR5K_AR5212_PHY_SPENDING_AR5112); + + /* + * Disable beacons and reset the register + */ + AR5K_REG_DISABLE_BITS(AR5K_AR5212_BEACON, + AR5K_AR5212_BEACON_ENABLE | AR5K_AR5212_BEACON_RESET_TSF); + + return (AH_TRUE); +} + +void +ar5k_ar5212_setPCUConfig(hal) + struct ath_hal *hal; +{ + u_int32_t pcu_reg, low_id, high_id; + + pcu_reg = 0; + + switch (hal->ah_op_mode) { + case IEEE80211_M_IBSS: + pcu_reg |= AR5K_AR5212_STA_ID1_ADHOC | + AR5K_AR5212_STA_ID1_DESC_ANTENNA; + break; + + case IEEE80211_M_HOSTAP: + pcu_reg |= AR5K_AR5212_STA_ID1_AP | + AR5K_AR5212_STA_ID1_RTS_DEFAULT_ANTENNA; + break; + + case IEEE80211_M_STA: + case IEEE80211_M_MONITOR: + pcu_reg |= AR5K_AR5212_STA_ID1_DEFAULT_ANTENNA; + break; + + default: + return; + } + + /* + * Set PCU registers + */ + memcpy(&low_id, &(hal->ah_sta_id[0]), 4); + memcpy(&high_id, &(hal->ah_sta_id[4]), 2); + AR5K_REG_WRITE(AR5K_AR5212_STA_ID0, low_id); + AR5K_REG_WRITE(AR5K_AR5212_STA_ID1, pcu_reg | high_id); + + return; +} + +HAL_BOOL +ar5k_ar5212_perCalibration(hal, channel) + struct ath_hal *hal; + HAL_CHANNEL *channel; +{ + u_int32_t i_pwr, q_pwr; + int32_t iq_corr, i_coff, i_coffd, q_coff, q_coffd; + + if (hal->ah_calibration == AH_FALSE || + AR5K_REG_READ(AR5K_AR5212_PHY_IQ) & AR5K_AR5212_PHY_IQ_RUN) + goto done; + + hal->ah_calibration = AH_FALSE; + + iq_corr = AR5K_REG_READ(AR5K_AR5212_PHY_IQRES_CAL_CORR); + i_pwr = AR5K_REG_READ(AR5K_AR5212_PHY_IQRES_CAL_PWR_I); + q_pwr = AR5K_REG_READ(AR5K_AR5212_PHY_IQRES_CAL_PWR_Q); + i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; + q_coffd = q_pwr >> 6; + + if (i_coffd == 0 || q_coffd == 0) + goto done; + + i_coff = ((-iq_corr) / i_coffd) & 0x3f; + q_coff = (((int32_t)i_pwr / q_coffd) - 64) & 0x1f; + + /* Commit new IQ value */ + AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_IQ, + AR5K_AR5212_PHY_IQ_CORR_ENABLE | + ((u_int32_t)q_coff) | + ((u_int32_t)i_coff << AR5K_AR5212_PHY_IQ_CORR_Q_I_COFF_S)); + + done: + /* Start noise floor calibration */ + AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_AGCCTL, + AR5K_AR5212_PHY_AGCCTL_NF); + + return (AH_TRUE); +} + +/* + * Transmit functions + */ + +HAL_BOOL +ar5k_ar5212_updateTxTrigLevel(hal, increase) + struct ath_hal *hal; + HAL_BOOL increase; +{ + u_int32_t trigger_level, imr; + HAL_BOOL status = AH_FALSE; + + /* + * Disable interrupts by setting the mask + */ + imr = ar5k_ar5212_setInterrupts(hal, hal->ah_imr & ~HAL_INT_GLOBAL); + + trigger_level = AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5212_TXCFG), + AR5K_AR5212_TXCFG_TXFULL); + + if (increase == AH_FALSE) { + if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) + goto done; + } else + trigger_level += + ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2); + + /* + * Update trigger level on success + */ + AR5K_REG_WRITE_BITS(AR5K_AR5212_TXCFG, + AR5K_AR5212_TXCFG_TXFULL, trigger_level); + status = AH_TRUE; + + done: + /* + * Restore interrupt mask + */ + ar5k_ar5212_setInterrupts(hal, imr); + + return (status); +} + +int +ar5k_ar5212_setupTxQueue(hal, queue_type, queue_info) + struct ath_hal *hal; + HAL_TX_QUEUE queue_type; + const HAL_TXQ_INFO *queue_info; +{ + u_int queue; + + /* + * Get queue by type + */ + if (queue_type == HAL_TX_QUEUE_DATA) { + for (queue = HAL_TX_QUEUE_ID_DATA_MIN; + hal->ah_txq[queue].tqi_type != HAL_TX_QUEUE_INACTIVE; + queue++) + if (queue > HAL_TX_QUEUE_ID_DATA_MAX) + return (-1); + } else if (queue_type == HAL_TX_QUEUE_PSPOLL) { + queue = HAL_TX_QUEUE_ID_PSPOLL; + } else if (queue_type == HAL_TX_QUEUE_BEACON) { + queue = HAL_TX_QUEUE_ID_BEACON; + } else if (queue_type == HAL_TX_QUEUE_CAB) { + queue = HAL_TX_QUEUE_ID_CAB; + } else + return (-1); + + /* + * Setup internal queue structure + */ + bzero(&hal->ah_txq[queue], sizeof(HAL_TXQ_INFO)); + hal->ah_txq[queue].tqi_type = queue_type; + + if (queue_info != NULL) { + if (ar5k_ar5212_setTxQueueProps(hal, queue, queue_info) + != AH_TRUE) + return (-1); + } + + AR5K_Q_ENABLE_BITS(hal->ah_txq_interrupts, queue); + + return (queue); +} + +HAL_BOOL +ar5k_ar5212_setTxQueueProps(hal, queue, queue_info) + struct ath_hal *hal; + int queue; + const HAL_TXQ_INFO *queue_info; +{ + AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); + + if (hal->ah_txq[queue].tqi_type == HAL_TX_QUEUE_INACTIVE) + return (AH_FALSE); + + bcopy(queue_info, &hal->ah_txq[queue], sizeof(HAL_TXQ_INFO)); + + if (queue_info->tqi_type == HAL_TX_QUEUE_DATA && + (queue_info->tqi_subtype >= HAL_WME_AC_VI) && + (queue_info->tqi_subtype <= HAL_WME_UPSD)) + hal->ah_txq[queue].tqi_flags |= + AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_releaseTxQueue(hal, queue) + struct ath_hal *hal; + u_int queue; +{ + AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); + + /* This queue will be skipped in further operations */ + hal->ah_txq[queue].tqi_type = HAL_TX_QUEUE_INACTIVE; + AR5K_Q_DISABLE_BITS(hal->ah_txq_interrupts, queue); + + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5212_resetTxQueue(hal, queue) + struct ath_hal *hal; + u_int queue; +{ + u_int32_t cw_min, cw_max, retry_lg, retry_sh; + struct ieee80211_channel *channel = (struct ieee80211_channel*) + &hal->ah_current_channel; + HAL_TXQ_INFO *tq; + + AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); + + tq = &hal->ah_txq[queue]; + + if (tq->tqi_type == HAL_TX_QUEUE_INACTIVE) + return (AH_TRUE); + + /* + * Set registers by channel mode + */ + if (IEEE80211_IS_CHAN_XR(channel)) { + hal->ah_cw_min = AR5K_TUNE_CWMIN_XR; + hal->ah_cw_max = AR5K_TUNE_CWMAX_XR; + hal->ah_aifs = AR5K_TUNE_AIFS_XR; + } else if (IEEE80211_IS_CHAN_B(channel)) { + hal->ah_cw_min = AR5K_TUNE_CWMIN_11B; + hal->ah_cw_max = AR5K_TUNE_CWMAX_11B; + hal->ah_aifs = AR5K_TUNE_AIFS_11B; + } else { + hal->ah_cw_min = AR5K_TUNE_CWMIN; + hal->ah_cw_max = AR5K_TUNE_CWMAX; + hal->ah_aifs = AR5K_TUNE_AIFS; + } + + /* + * Set retry limits + */ + if (hal->ah_software_retry == AH_TRUE) { + /* XXX Need to test this */ + retry_lg = hal->ah_limit_tx_retries; + retry_sh = retry_lg = + retry_lg > AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY ? + AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY : retry_lg; + } else { + retry_lg = AR5K_INIT_LG_RETRY; + retry_sh = AR5K_INIT_SH_RETRY; + } + + AR5K_REG_WRITE(AR5K_AR5212_DCU_RETRY_LMT(queue), + AR5K_REG_SM(AR5K_INIT_SLG_RETRY, + AR5K_AR5212_DCU_RETRY_LMT_SLG_RETRY) + | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, + AR5K_AR5212_DCU_RETRY_LMT_SSH_RETRY) + | AR5K_REG_SM(retry_lg, AR5K_AR5212_DCU_RETRY_LMT_LG_RETRY) + | AR5K_REG_SM(retry_sh, AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY)); + + /* + * Set initial content window (cw_min/cw_max) + */ + cw_min = 1; + while (cw_min < hal->ah_cw_min) + cw_min = (cw_min << 1) | 1; + + cw_min = tq->tqi_cw_min < 0 ? + (cw_min >> (-tq->tqi_cw_min)) : + ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); + cw_max = tq->tqi_cw_max < 0 ? + (cw_max >> (-tq->tqi_cw_max)) : + ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); + + AR5K_REG_WRITE(AR5K_AR5212_DCU_LCL_IFS(queue), + AR5K_REG_SM(cw_min, AR5K_AR5212_DCU_LCL_IFS_CW_MIN) | + AR5K_REG_SM(cw_max, AR5K_AR5212_DCU_LCL_IFS_CW_MAX) | + AR5K_REG_SM(hal->ah_aifs + tq->tqi_aifs, + AR5K_AR5212_DCU_LCL_IFS_AIFS)); + + /* + * Set misc registers + */ + AR5K_REG_WRITE(AR5K_AR5212_QCU_MISC(queue), + AR5K_AR5212_QCU_MISC_DCU_EARLY); + + if (tq->tqi_cbr_period) { + AR5K_REG_WRITE(AR5K_AR5212_QCU_CBRCFG(queue), + AR5K_REG_SM(tq->tqi_cbr_period, + AR5K_AR5212_QCU_CBRCFG_INTVAL) | + AR5K_REG_SM(tq->tqi_cbr_overflow_limit, + AR5K_AR5212_QCU_CBRCFG_ORN_THRES)); + AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), + AR5K_AR5212_QCU_MISC_FRSHED_CBR); + if (tq->tqi_cbr_overflow_limit) + AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), + AR5K_AR5212_QCU_MISC_CBR_THRES_ENABLE); + } + + if (tq->tqi_ready_time) { + AR5K_REG_WRITE(AR5K_AR5212_QCU_RDYTIMECFG(queue), + AR5K_REG_SM(tq->tqi_ready_time, + AR5K_AR5212_QCU_RDYTIMECFG_INTVAL) | + AR5K_AR5212_QCU_RDYTIMECFG_ENABLE); + } + + if (tq->tqi_burst_time) { + AR5K_REG_WRITE(AR5K_AR5212_DCU_CHAN_TIME(queue), + AR5K_REG_SM(tq->tqi_burst_time, + AR5K_AR5212_DCU_CHAN_TIME_DUR) | + AR5K_AR5212_DCU_CHAN_TIME_ENABLE); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) { + AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), + AR5K_AR5212_QCU_MISC_TXE); + } + } + + if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) { + AR5K_REG_WRITE(AR5K_AR5212_DCU_MISC(queue), + AR5K_AR5212_DCU_MISC_POST_FR_BKOFF_DIS); + } + + if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { + AR5K_REG_WRITE(AR5K_AR5212_DCU_MISC(queue), + AR5K_AR5212_DCU_MISC_BACKOFF_FRAG); + } + + /* + * Set registers by queue type + */ + switch (tq->tqi_type) { + case HAL_TX_QUEUE_BEACON: + AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), + AR5K_AR5212_QCU_MISC_FRSHED_DBA_GT | + AR5K_AR5212_QCU_MISC_CBREXP_BCN | + AR5K_AR5212_QCU_MISC_BCN_ENABLE); + + AR5K_REG_ENABLE_BITS(AR5K_AR5212_DCU_MISC(queue), + (AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL << + AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL) | + AR5K_AR5212_DCU_MISC_POST_FR_BKOFF_DIS | + AR5K_AR5212_DCU_MISC_BCN_ENABLE); + + AR5K_REG_WRITE(AR5K_AR5212_QCU_RDYTIMECFG(queue), + ((AR5K_TUNE_BEACON_INTERVAL - + (AR5K_TUNE_SW_BEACON_RESP - AR5K_TUNE_DMA_BEACON_RESP) - + AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | + AR5K_AR5212_QCU_RDYTIMECFG_ENABLE); + break; + + case HAL_TX_QUEUE_CAB: + AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), + AR5K_AR5212_QCU_MISC_FRSHED_DBA_GT | + AR5K_AR5212_QCU_MISC_CBREXP | + AR5K_AR5212_QCU_MISC_CBREXP_BCN); + + AR5K_REG_ENABLE_BITS(AR5K_AR5212_DCU_MISC(queue), + (AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL << + AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL)); + break; + + case HAL_TX_QUEUE_PSPOLL: + AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue), + AR5K_AR5212_QCU_MISC_CBREXP); + break; + + case HAL_TX_QUEUE_DATA: + default: + break; + } + + /* + * Enable tx queue in the secondary interrupt mask registers + */ + AR5K_REG_WRITE(AR5K_AR5212_SIMR0, + AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR0_QCU_TXOK) | + AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR0_QCU_TXDESC)); + AR5K_REG_WRITE(AR5K_AR5212_SIMR1, + AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR1_QCU_TXERR)); + AR5K_REG_WRITE(AR5K_AR5212_SIMR2, + AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR2_QCU_TXURN)); + + return (AH_TRUE); +} + +u_int32_t +ar5k_ar5212_getTxDP(hal, queue) + struct ath_hal *hal; + u_int queue; +{ + AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); + + /* + * Get the transmit queue descriptor pointer from the selected queue + */ + return (AR5K_REG_READ(AR5K_AR5212_QCU_TXDP(queue))); +} + +HAL_BOOL +ar5k_ar5212_setTxDP(hal, queue, phys_addr) + struct ath_hal *hal; + u_int queue; + u_int32_t phys_addr; +{ + AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); + + /* + * Set the transmit queue descriptor pointer for the selected queue + * (this won't work if the queue is still active) + */ + if (AR5K_REG_READ_Q(AR5K_AR5212_QCU_TXE, queue)) + return (AH_FALSE); + + AR5K_REG_WRITE(AR5K_AR5212_QCU_TXDP(queue), phys_addr); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_startTxDma(hal, queue) + struct ath_hal *hal; + u_int queue; +{ + AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); + + /* Return if queue is disabled */ + if (AR5K_REG_READ_Q(AR5K_AR5212_QCU_TXD, queue)) + return (AH_FALSE); + + /* Start queue */ + AR5K_REG_WRITE_Q(AR5K_AR5212_QCU_TXE, queue); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_stopTxDma(hal, queue) + struct ath_hal *hal; + u_int queue; +{ + HAL_BOOL ret; + + AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num); + + /* + * Schedule TX disable and wait until queue is empty + */ + AR5K_REG_WRITE_Q(AR5K_AR5212_QCU_TXD, queue); + + ret = ar5k_register_timeout(hal, AR5K_AR5212_QCU_STS(queue), + AR5K_AR5212_QCU_STS_FRMPENDCNT, 0, AH_FALSE); + + /* Clear register */ + AR5K_REG_WRITE(AR5K_AR5212_QCU_TXD, 0); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_setupTxDesc(hal, desc, packet_length, header_length, type, tx_power, + tx_rate0, tx_tries0, key_index, antenna_mode, flags, rtscts_rate, + rtscts_duration) + struct ath_hal *hal; + struct ath_desc *desc; + u_int packet_length; + u_int header_length; + HAL_PKT_TYPE type; + u_int tx_power; + u_int tx_rate0; + u_int tx_tries0; + u_int key_index; + u_int antenna_mode; + u_int flags; + u_int rtscts_rate; + u_int rtscts_duration; +{ + struct ar5k_ar5212_tx_desc *tx_desc; + + tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0; + + /* Clear descriptor */ + bzero(tx_desc, sizeof(struct ar5k_ar5212_tx_desc)); + + /* + * Validate input + */ + if (tx_tries0 == 0) + return (AH_FALSE); + + if ((tx_desc->frame_len = packet_length) != packet_length) + return (AH_FALSE); + + tx_desc->frame_type = type; + tx_desc->xmit_power = tx_power; + tx_desc->xmit_rate0 = tx_rate0; + tx_desc->xmit_tries0 = tx_tries0; + tx_desc->ant_mode_xmit = antenna_mode; + +#define _TX_FLAGS(_flag, _field) \ + tx_desc->_field = flags & HAL_TXDESC_##_flag ? 1 : 0 + + _TX_FLAGS(CLRDMASK, clear_dest_mask); + _TX_FLAGS(VEOL, veol); + _TX_FLAGS(INTREQ, inter_req); + _TX_FLAGS(NOACK, no_ack); + _TX_FLAGS(RTSENA, rts_cts_enable); + _TX_FLAGS(CTSENA, cts_enable); + +#undef _TX_FLAGS + + /* + * WEP crap + */ + if (key_index != HAL_TXKEYIX_INVALID) { + tx_desc->encrypt_key_valid = 1; + tx_desc->encrypt_key_index = key_index; + } + + /* + * RTS/CTS + */ + if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) { + if ((flags & HAL_TXDESC_RTSENA) && + (flags & HAL_TXDESC_CTSENA)) + return (AH_FALSE); + tx_desc->rts_cts_rate = rtscts_rate; + tx_desc->rts_duration = rtscts_duration; + } + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_fillTxDesc(hal, desc, segment_length, first_segment, last_segment) + struct ath_hal *hal; + struct ath_desc *desc; + u_int segment_length; + HAL_BOOL first_segment; + HAL_BOOL last_segment; +{ + struct ar5k_ar5212_tx_desc *tx_desc; + + tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0; + + /* Clear status descriptor */ + desc->ds_hw[0] = desc->ds_hw[1] = 0; + + /* Validate segment length and initialize the descriptor */ + if ((tx_desc->buf_len = segment_length) != segment_length) + return (AH_FALSE); + + if (first_segment != AH_TRUE) + tx_desc->frame_len = 0; + + tx_desc->more = last_segment == AH_TRUE ? 0 : 1; + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_setupXTxDesc(hal, desc, tx_rate1, tx_tries1, tx_rate2, tx_tries2, + tx_rate3, tx_tries3) + struct ath_hal *hal; + struct ath_desc *desc; + u_int tx_rate1; + u_int tx_tries1; + u_int tx_rate2; + u_int tx_tries2; + u_int tx_rate3; + u_int tx_tries3; +{ + struct ar5k_ar5212_tx_desc *tx_desc; + + tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0; + +#define _XTX_TRIES(_n) \ + if (tx_tries##_n) { \ + tx_desc->xmit_tries##_n = tx_tries##_n; \ + tx_desc->xmit_rate##_n = tx_rate##_n; \ + } + + _XTX_TRIES(1); + _XTX_TRIES(2); + _XTX_TRIES(3); + +#undef _XTX_TRIES + + return (AH_TRUE); +} + +HAL_STATUS +ar5k_ar5212_procTxDesc(hal, desc) + struct ath_hal *hal; + struct ath_desc *desc; +{ + struct ar5k_ar5212_tx_status *tx_status; + struct ar5k_ar5212_tx_desc *tx_desc; + + tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0; + tx_status = (struct ar5k_ar5212_tx_status*)&desc->ds_hw[0]; + + /* No frame has been send or error */ + if (tx_status->done == 0) + return (HAL_EINPROGRESS); + + /* + * Get descriptor status + */ + desc->ds_us.tx.ts_seqnum = tx_status->seq_num; + desc->ds_us.tx.ts_tstamp = tx_status->send_timestamp; + desc->ds_us.tx.ts_shortretry = tx_status->rts_fail_count; + desc->ds_us.tx.ts_longretry = tx_status->data_fail_count; + desc->ds_us.tx.ts_rssi = tx_status->ack_sig_strength; + desc->ds_us.tx.ts_antenna = tx_status->xmit_antenna ? 2 : 1; + desc->ds_us.tx.ts_status = 0; + + switch (tx_status->final_ts_index) { + case 0: + desc->ds_us.tx.ts_rate = tx_desc->xmit_rate0; + break; + case 1: + desc->ds_us.tx.ts_rate = tx_desc->xmit_rate1; + desc->ds_us.tx.ts_longretry += tx_desc->xmit_tries0; + break; + case 2: + desc->ds_us.tx.ts_rate = tx_desc->xmit_rate2; + desc->ds_us.tx.ts_longretry += tx_desc->xmit_tries1; + break; + case 3: + desc->ds_us.tx.ts_rate = tx_desc->xmit_rate3; + desc->ds_us.tx.ts_longretry += tx_desc->xmit_tries2; + break; + } + + if (tx_status->frame_xmit_ok == 0) { + if (tx_status->excessive_retries) + desc->ds_us.tx.ts_status |= HAL_TXERR_XRETRY; + + if (tx_status->fifo_underrun) + desc->ds_us.tx.ts_status |= HAL_TXERR_FIFO; + + if (tx_status->filtered) + desc->ds_us.tx.ts_status |= HAL_TXERR_FILT; + } + + return (HAL_OK); +} + +HAL_BOOL +ar5k_ar5212_hasVEOL(hal) + struct ath_hal *hal; +{ + return (AH_TRUE); +} + +/* + * Receive functions + */ + +u_int32_t +ar5k_ar5212_getRxDP(hal) + struct ath_hal *hal; +{ + return (AR5K_REG_READ(AR5K_AR5212_RXDP)); +} + +void +ar5k_ar5212_setRxDP(hal, phys_addr) + struct ath_hal *hal; + u_int32_t phys_addr; +{ + AR5K_REG_WRITE(AR5K_AR5212_RXDP, phys_addr); +} + +void +ar5k_ar5212_enableReceive(hal) + struct ath_hal *hal; +{ + AR5K_REG_WRITE(AR5K_AR5212_CR, AR5K_AR5212_CR_RXE); +} + +HAL_BOOL +ar5k_ar5212_stopDmaReceive(hal) + struct ath_hal *hal; +{ + int i; + + AR5K_REG_WRITE(AR5K_AR5212_CR, AR5K_AR5212_CR_RXD); + + /* + * It may take some time to disable the DMA receive unit + */ + for (i = 2000; + i > 0 && (AR5K_REG_READ(AR5K_AR5212_CR) & AR5K_AR5212_CR_RXE) != 0; + i--) + AR5K_DELAY(10); + + return (i > 0 ? AH_TRUE : AH_FALSE); +} + +void +ar5k_ar5212_startPcuReceive(hal) + struct ath_hal *hal; +{ + AR5K_REG_DISABLE_BITS(AR5K_AR5212_DIAG_SW, AR5K_AR5212_DIAG_SW_DIS_RX); +} + +void +ar5k_ar5212_stopPcuReceive(hal) + struct ath_hal *hal; +{ + AR5K_REG_ENABLE_BITS(AR5K_AR5212_DIAG_SW, AR5K_AR5212_DIAG_SW_DIS_RX); +} + +void +ar5k_ar5212_setMulticastFilter(hal, filter0, filter1) + struct ath_hal *hal; + u_int32_t filter0; + u_int32_t filter1; +{ + /* Set the multicat filter */ + AR5K_REG_WRITE(AR5K_AR5212_MCAST_FIL0, filter0); + AR5K_REG_WRITE(AR5K_AR5212_MCAST_FIL1, filter1); +} + +HAL_BOOL +ar5k_ar5212_setMulticastFilterIndex(hal, index) + struct ath_hal *hal; + u_int32_t index; +{ + if (index >= 64) { + return (AH_FALSE); + } else if (index >= 32) { + AR5K_REG_ENABLE_BITS(AR5K_AR5212_MCAST_FIL1, + (1 << (index - 32))); + } else { + AR5K_REG_ENABLE_BITS(AR5K_AR5212_MCAST_FIL0, + (1 << index)); + } + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_clrMulticastFilterIndex(hal, index) + struct ath_hal *hal; + u_int32_t index; +{ + + if (index >= 64) { + return (AH_FALSE); + } else if (index >= 32) { + AR5K_REG_DISABLE_BITS(AR5K_AR5212_MCAST_FIL1, + (1 << (index - 32))); + } else { + AR5K_REG_DISABLE_BITS(AR5K_AR5212_MCAST_FIL0, + (1 << index)); + } + + return (AH_TRUE); +} + +u_int32_t +ar5k_ar5212_getRxFilter(hal) + struct ath_hal *hal; +{ + u_int32_t data, filter = 0; + + filter = AR5K_REG_READ(AR5K_AR5212_RX_FILTER); + data = AR5K_REG_READ(AR5K_AR5212_PHY_ERR_FIL); + + if (data & AR5K_AR5212_PHY_ERR_FIL_RADAR) + filter |= HAL_RX_FILTER_PHYRADAR; + if (data & (AR5K_AR5212_PHY_ERR_FIL_OFDM | + AR5K_AR5212_PHY_ERR_FIL_CCK)) + filter |= HAL_RX_FILTER_PHYERR; + + return (filter); +} + +void +ar5k_ar5212_setRxFilter(hal, filter) + struct ath_hal *hal; + u_int32_t filter; +{ + u_int32_t data = 0; + + if (filter & HAL_RX_FILTER_PHYRADAR) + data |= AR5K_AR5212_PHY_ERR_FIL_RADAR; + if (filter & HAL_RX_FILTER_PHYERR) + data |= AR5K_AR5212_PHY_ERR_FIL_OFDM | + AR5K_AR5212_PHY_ERR_FIL_CCK; + + if (data) { + AR5K_REG_ENABLE_BITS(AR5K_AR5212_RXCFG, + AR5K_AR5212_RXCFG_ZLFDMA); + } else { + AR5K_REG_DISABLE_BITS(AR5K_AR5212_RXCFG, + AR5K_AR5212_RXCFG_ZLFDMA); + } + + AR5K_REG_WRITE(AR5K_AR5212_RX_FILTER, filter & 0xff); + AR5K_REG_WRITE(AR5K_AR5212_PHY_ERR_FIL, data); +} + +HAL_BOOL +ar5k_ar5212_setupRxDesc(hal, desc, size, flags) + struct ath_hal *hal; + struct ath_desc *desc; + u_int32_t size; + u_int flags; +{ + struct ar5k_ar5212_rx_desc *rx_desc; + + /* Reset descriptor */ + desc->ds_ctl0 = 0; + desc->ds_ctl1 = 0; + bzero(&desc->ds_hw[0], sizeof(struct ar5k_ar5212_rx_status)); + + rx_desc = (struct ar5k_ar5212_rx_desc*)&desc->ds_ctl0; + + if ((rx_desc->buf_len = size) != size) + return (AH_FALSE); + + if (flags & HAL_RXDESC_INTREQ) + rx_desc->inter_req = 1; + + return (AH_TRUE); +} + +HAL_STATUS +ar5k_ar5212_procRxDesc(hal, desc, phys_addr, next) + struct ath_hal *hal; + struct ath_desc *desc; + u_int32_t phys_addr; + struct ath_desc *next; +{ + u_int32_t now, tstamp; + struct ar5k_ar5212_rx_status *rx_status; + + rx_status = (struct ar5k_ar5212_rx_status*)&desc->ds_hw[0]; + + /* No frame received / not ready */ + if (!rx_status->done) + return (HAL_EINPROGRESS); + + /* + * Frame receive status + */ + now = (AR5K_REG_READ(AR5K_AR5212_TSF_L32) >> 10) & 0xffff; + tstamp = ((now & 0x1fff) < rx_status->receive_timestamp) ? + (((now - 0x2000) & 0xffff) | + (u_int32_t)rx_status->receive_timestamp) : + (now | (u_int32_t)rx_status->receive_timestamp); + desc->ds_us.rx.rs_tstamp = rx_status->receive_timestamp & 0x7fff; + desc->ds_us.rx.rs_datalen = rx_status->data_len; + desc->ds_us.rx.rs_rssi = rx_status->receive_sig_strength; + desc->ds_us.rx.rs_rate = rx_status->receive_rate; + desc->ds_us.rx.rs_antenna = rx_status->receive_antenna ? 1 : 0; + desc->ds_us.rx.rs_more = rx_status->more ? 1 : 0; + desc->ds_us.rx.rs_status = 0; + + /* + * Key table status + */ + if (!rx_status->key_index_valid) { + desc->ds_us.rx.rs_keyix = HAL_RXKEYIX_INVALID; + } else { + desc->ds_us.rx.rs_keyix = rx_status->key_index; + } + + /* + * Receive/descriptor errors + */ + if (!rx_status->frame_receive_ok) { + if (rx_status->crc_error) + desc->ds_us.rx.rs_status |= HAL_RXERR_CRC; + + if (rx_status->phy_error) { + desc->ds_us.rx.rs_status |= HAL_RXERR_PHY; + desc->ds_us.rx.rs_phyerr = rx_status->phy_error; + } + + if (rx_status->decrypt_crc_error) + desc->ds_us.rx.rs_status |= HAL_RXERR_DECRYPT; + + if (rx_status->mic_error) + desc->ds_us.rx.rs_status |= HAL_RXERR_MIC; + } + + return (HAL_OK); +} + +void +ar5k_ar5212_rxMonitor(hal) + struct ath_hal *hal; +{ + AR5K_REG_ENABLE_BITS(AR5K_AR5212_RX_FILTER, + AR5K_AR5212_RX_FILTER_PROMISC); +} + +/* + * Misc functions + */ + +void +ar5k_ar5212_dumpState(hal) + struct ath_hal *hal; +{ +#ifdef AR5K_DEBUG +#define AR5K_PRINT_REGISTER(_x) \ + printf("(%s: %08x) ", #_x, AR5K_REG_READ(AR5K_AR5212_##_x)); + + printf("MAC registers:\n"); + AR5K_PRINT_REGISTER(CR); + AR5K_PRINT_REGISTER(CFG); + AR5K_PRINT_REGISTER(IER); + AR5K_PRINT_REGISTER(TXCFG); + AR5K_PRINT_REGISTER(RXCFG); + AR5K_PRINT_REGISTER(MIBC); + AR5K_PRINT_REGISTER(TOPS); + AR5K_PRINT_REGISTER(RXNOFRM); + AR5K_PRINT_REGISTER(RPGTO); + AR5K_PRINT_REGISTER(RFCNT); + AR5K_PRINT_REGISTER(MISC); + AR5K_PRINT_REGISTER(PISR); + AR5K_PRINT_REGISTER(SISR0); + AR5K_PRINT_REGISTER(SISR1); + AR5K_PRINT_REGISTER(SISR3); + AR5K_PRINT_REGISTER(SISR4); + AR5K_PRINT_REGISTER(DCM_ADDR); + AR5K_PRINT_REGISTER(DCM_DATA); + AR5K_PRINT_REGISTER(DCCFG); + AR5K_PRINT_REGISTER(CCFG); + AR5K_PRINT_REGISTER(CCFG_CUP); + AR5K_PRINT_REGISTER(CPC0); + AR5K_PRINT_REGISTER(CPC1); + AR5K_PRINT_REGISTER(CPC2); + AR5K_PRINT_REGISTER(CPCORN); + AR5K_PRINT_REGISTER(QCU_TXE); + AR5K_PRINT_REGISTER(QCU_TXD); + AR5K_PRINT_REGISTER(DCU_GBL_IFS_SIFS); + AR5K_PRINT_REGISTER(DCU_GBL_IFS_SLOT); + AR5K_PRINT_REGISTER(DCU_FP); + AR5K_PRINT_REGISTER(DCU_TXP); + AR5K_PRINT_REGISTER(DCU_TX_FILTER); + AR5K_PRINT_REGISTER(RC); + AR5K_PRINT_REGISTER(SCR); + AR5K_PRINT_REGISTER(INTPEND); + AR5K_PRINT_REGISTER(PCICFG); + AR5K_PRINT_REGISTER(GPIOCR); + AR5K_PRINT_REGISTER(GPIODO); + AR5K_PRINT_REGISTER(SREV); + AR5K_PRINT_REGISTER(EEPROM_BASE); + AR5K_PRINT_REGISTER(EEPROM_DATA); + AR5K_PRINT_REGISTER(EEPROM_CMD); + AR5K_PRINT_REGISTER(EEPROM_CFG); + AR5K_PRINT_REGISTER(PCU_MIN); + AR5K_PRINT_REGISTER(STA_ID0); + AR5K_PRINT_REGISTER(STA_ID1); + AR5K_PRINT_REGISTER(BSS_ID0); + AR5K_PRINT_REGISTER(SLOT_TIME); + AR5K_PRINT_REGISTER(TIME_OUT); + AR5K_PRINT_REGISTER(RSSI_THR); + AR5K_PRINT_REGISTER(BEACON); + AR5K_PRINT_REGISTER(CFP_PERIOD); + AR5K_PRINT_REGISTER(TIMER0); + AR5K_PRINT_REGISTER(TIMER2); + AR5K_PRINT_REGISTER(TIMER3); + AR5K_PRINT_REGISTER(CFP_DUR); + AR5K_PRINT_REGISTER(MCAST_FIL0); + AR5K_PRINT_REGISTER(MCAST_FIL1); + AR5K_PRINT_REGISTER(DIAG_SW); + AR5K_PRINT_REGISTER(TSF_U32); + AR5K_PRINT_REGISTER(ADDAC_TEST); + AR5K_PRINT_REGISTER(DEFAULT_ANTENNA); + AR5K_PRINT_REGISTER(LAST_TSTP); + AR5K_PRINT_REGISTER(NAV); + AR5K_PRINT_REGISTER(RTS_OK); + AR5K_PRINT_REGISTER(ACK_FAIL); + AR5K_PRINT_REGISTER(FCS_FAIL); + AR5K_PRINT_REGISTER(BEACON_CNT); + AR5K_PRINT_REGISTER(TSF_PARM); + AR5K_PRINT_REGISTER(RATE_DUR_0); + AR5K_PRINT_REGISTER(KEYTABLE_0); + printf("\n"); + + printf("PHY registers:\n"); + AR5K_PRINT_REGISTER(PHY_TURBO); + AR5K_PRINT_REGISTER(PHY_AGC); + AR5K_PRINT_REGISTER(PHY_TIMING_3); + AR5K_PRINT_REGISTER(PHY_CHIP_ID); + AR5K_PRINT_REGISTER(PHY_AGCCTL); + AR5K_PRINT_REGISTER(PHY_NF); + AR5K_PRINT_REGISTER(PHY_RX_DELAY); + AR5K_PRINT_REGISTER(PHY_IQ); + AR5K_PRINT_REGISTER(PHY_PAPD_PROBE); + AR5K_PRINT_REGISTER(PHY_TXPOWER_RATE1); + AR5K_PRINT_REGISTER(PHY_TXPOWER_RATE2); + AR5K_PRINT_REGISTER(PHY_FC); + AR5K_PRINT_REGISTER(PHY_RADAR); + AR5K_PRINT_REGISTER(PHY_ANT_SWITCH_TABLE_0); + AR5K_PRINT_REGISTER(PHY_ANT_SWITCH_TABLE_1); + printf("\n"); +#endif +} + +HAL_BOOL +ar5k_ar5212_getDiagState(hal, id, device, size) + struct ath_hal *hal; + int id; + void **device; + u_int *size; + +{ + /* + * We'll ignore this right now. This seems to be some kind of an obscure + * debugging interface for the binary-only HAL. + */ + return (AH_FALSE); +} + +void +ar5k_ar5212_getMacAddress(hal, mac) + struct ath_hal *hal; + u_int8_t *mac; +{ + memcpy(mac, hal->ah_sta_id, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5k_ar5212_setMacAddress(hal, mac) + struct ath_hal *hal; + const u_int8_t *mac; +{ + u_int32_t low_id, high_id; + + /* Set new station ID */ + memcpy(hal->ah_sta_id, mac, IEEE80211_ADDR_LEN); + + memcpy(&low_id, mac, 4); + memcpy(&high_id, mac + 4, 2); + high_id = 0x0000ffff & htole32(high_id); + + AR5K_REG_WRITE(AR5K_AR5212_STA_ID0, htole32(low_id)); + AR5K_REG_WRITE(AR5K_AR5212_STA_ID1, high_id); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_setRegulatoryDomain(hal, regdomain, status) + struct ath_hal *hal; + u_int16_t regdomain; + HAL_STATUS *status; + +{ + ieee80211_regdomain_t ieee_regdomain; + + ieee_regdomain = ar5k_regdomain_to_ieee(regdomain); + + if (ar5k_eeprom_regulation_domain(hal, AH_TRUE, + &ieee_regdomain) == AH_TRUE) { + *status = HAL_OK; + return (AH_TRUE); + } + + *status = EIO; + + return (AH_FALSE); +} + +void +ar5k_ar5212_setLedState(hal, state) + struct ath_hal *hal; + HAL_LED_STATE state; +{ + u_int32_t led; + + AR5K_REG_DISABLE_BITS(AR5K_AR5212_PCICFG, + AR5K_AR5212_PCICFG_LEDMODE | AR5K_AR5212_PCICFG_LED); + + /* + * Some blinking values, define at your wish + */ + switch (state) { + case IEEE80211_S_SCAN: + case IEEE80211_S_AUTH: + led = + AR5K_AR5212_PCICFG_LEDMODE_PROP | + AR5K_AR5212_PCICFG_LED_PEND; + break; + + case IEEE80211_S_INIT: + led = + AR5K_AR5212_PCICFG_LEDMODE_PROP | + AR5K_AR5212_PCICFG_LED_NONE; + break; + + case IEEE80211_S_ASSOC: + case IEEE80211_S_RUN: + led |= + AR5K_AR5212_PCICFG_LEDMODE_PROP | + AR5K_AR5212_PCICFG_LED_ASSOC; + break; + + default: + led |= + AR5K_AR5212_PCICFG_LEDMODE_PROM | + AR5K_AR5212_PCICFG_LED_NONE; + break; + } + + AR5K_REG_ENABLE_BITS(AR5K_AR5212_PCICFG, led); +} + +void +ar5k_ar5212_writeAssocid(hal, bssid, assoc_id, tim_offset) + struct ath_hal *hal; + const u_int8_t *bssid; + u_int16_t assoc_id; + u_int16_t tim_offset; +{ + u_int32_t low_id, high_id; + + /* + * Set simple BSSID mask + */ + AR5K_REG_WRITE(AR5K_AR5212_BSS_IDM0, 0xfffffff); + AR5K_REG_WRITE(AR5K_AR5212_BSS_IDM1, 0xfffffff); + + /* + * Set BSSID which triggers the "SME Join" operation + */ + memcpy(&low_id, bssid, 4); + memcpy(&high_id, bssid + 4, 2); + AR5K_REG_WRITE(AR5K_AR5212_BSS_ID0, htole32(low_id)); + AR5K_REG_WRITE(AR5K_AR5212_BSS_ID1, htole32(high_id) | + ((assoc_id & 0x3fff) << AR5K_AR5212_BSS_ID1_AID_S)); + memcpy(&hal->ah_bssid, bssid, IEEE80211_ADDR_LEN); + + if (assoc_id == 0) { + ar5k_ar5212_disablePSPoll(hal); + return; + } + + AR5K_REG_WRITE(AR5K_AR5212_BEACON, + (AR5K_REG_READ(AR5K_AR5212_BEACON) & + ~AR5K_AR5212_BEACON_TIM) | + (((tim_offset ? tim_offset + 4 : 0) << + AR5K_AR5212_BEACON_TIM_S) & + AR5K_AR5212_BEACON_TIM)); + + ar5k_ar5212_enablePSPoll(hal, NULL, 0); +} + +HAL_BOOL +ar5k_ar5212_gpioCfgOutput(hal, gpio) + struct ath_hal *hal; + u_int32_t gpio; +{ + if (gpio > AR5K_AR5212_NUM_GPIO) + return (AH_FALSE); + + AR5K_REG_WRITE(AR5K_AR5212_GPIOCR, + (AR5K_REG_READ(AR5K_AR5212_GPIOCR) &~ AR5K_AR5212_GPIOCR_ALL(gpio)) + | AR5K_AR5212_GPIOCR_ALL(gpio)); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_gpioCfgInput(hal, gpio) + struct ath_hal *hal; + u_int32_t gpio; +{ + if (gpio > AR5K_AR5212_NUM_GPIO) + return (AH_FALSE); + + AR5K_REG_WRITE(AR5K_AR5212_GPIOCR, + (AR5K_REG_READ(AR5K_AR5212_GPIOCR) &~ AR5K_AR5212_GPIOCR_ALL(gpio)) + | AR5K_AR5212_GPIOCR_NONE(gpio)); + + return (AH_TRUE); +} + +u_int32_t +ar5k_ar5212_gpioGet(hal, gpio) + struct ath_hal *hal; + u_int32_t gpio; +{ + if (gpio > AR5K_AR5212_NUM_GPIO) + return (0xffffffff); + + /* GPIO input magic */ + return (((AR5K_REG_READ(AR5K_AR5212_GPIODI) & + AR5K_AR5212_GPIODI_M) >> gpio) & 0x1); +} + +HAL_BOOL +ar5k_ar5212_gpioSet(hal, gpio, val) + struct ath_hal *hal; + u_int32_t gpio; + u_int32_t val; +{ + u_int32_t data; + + if (gpio > AR5K_AR5212_NUM_GPIO) + return (0xffffffff); + + /* GPIO output magic */ + data = AR5K_REG_READ(AR5K_AR5212_GPIODO); + + data &= ~(1 << gpio); + data |= (val&1) << gpio; + + AR5K_REG_WRITE(AR5K_AR5212_GPIODO, data); + + return (AH_TRUE); +} + +void +ar5k_ar5212_gpioSetIntr(hal, gpio, interrupt_level) + struct ath_hal *hal; + u_int gpio; + u_int32_t interrupt_level; +{ + u_int32_t data; + + if (gpio > AR5K_AR5212_NUM_GPIO) + return; + + /* + * Set the GPIO interrupt + */ + data = (AR5K_REG_READ(AR5K_AR5212_GPIOCR) & + ~(AR5K_AR5212_GPIOCR_INT_SEL(gpio) | AR5K_AR5212_GPIOCR_INT_SELH | + AR5K_AR5212_GPIOCR_INT_ENA | AR5K_AR5212_GPIOCR_ALL(gpio))) | + (AR5K_AR5212_GPIOCR_INT_SEL(gpio) | AR5K_AR5212_GPIOCR_INT_ENA); + + AR5K_REG_WRITE(AR5K_AR5212_GPIOCR, + interrupt_level ? data : (data | AR5K_AR5212_GPIOCR_INT_SELH)); + + hal->ah_imr |= AR5K_AR5212_PIMR_GPIO; + + /* Enable GPIO interrupts */ + AR5K_REG_ENABLE_BITS(AR5K_AR5212_PIMR, AR5K_AR5212_PIMR_GPIO); +} + +u_int32_t +ar5k_ar5212_getTsf32(hal) + struct ath_hal *hal; +{ + return (AR5K_REG_READ(AR5K_AR5212_TSF_L32)); +} + +u_int64_t +ar5k_ar5212_getTsf64(hal) + struct ath_hal *hal; +{ + u_int64_t tsf = AR5K_REG_READ(AR5K_AR5212_TSF_U32); + + return (AR5K_REG_READ(AR5K_AR5212_TSF_L32) | (tsf << 32)); +} + +void +ar5k_ar5212_resetTsf(hal) + struct ath_hal *hal; +{ + AR5K_REG_ENABLE_BITS(AR5K_AR5212_BEACON, + AR5K_AR5212_BEACON_RESET_TSF); +} + +u_int16_t +ar5k_ar5212_getRegDomain(hal) + struct ath_hal *hal; +{ + return (ar5k_get_regdomain(hal)); +} + +HAL_BOOL +ar5k_ar5212_detectCardPresent(hal) + struct ath_hal *hal; +{ + u_int16_t magic; + + /* + * Checking the EEPROM's magic value could be an indication + * if the card is still present. I didn't find another suitable + * way to do this. + */ + if (ar5k_ar5212_eeprom_read(hal, AR5K_EEPROM_MAGIC, &magic) != 0) + return (AH_FALSE); + + return (magic == AR5K_EEPROM_MAGIC_VALUE ? AH_TRUE : AH_FALSE); +} + +void +ar5k_ar5212_updateMibCounters(hal, statistics) + struct ath_hal *hal; + HAL_MIB_STATS *statistics; +{ + statistics->ackrcv_bad += AR5K_REG_READ(AR5K_AR5212_ACK_FAIL); + statistics->rts_bad += AR5K_REG_READ(AR5K_AR5212_RTS_FAIL); + statistics->rts_good += AR5K_REG_READ(AR5K_AR5212_RTS_OK); + statistics->fcs_bad += AR5K_REG_READ(AR5K_AR5212_FCS_FAIL); + statistics->beacons += AR5K_REG_READ(AR5K_AR5212_BEACON_CNT); +} + +HAL_RFGAIN +ar5k_ar5212_getRfGain(hal) + struct ath_hal *hal; +{ + return (HAL_RFGAIN_INACTIVE); +} + +HAL_BOOL +ar5k_ar5212_setSlotTime(hal, slot_time) + struct ath_hal *hal; + u_int slot_time; +{ + if (slot_time < HAL_SLOT_TIME_9 || slot_time > HAL_SLOT_TIME_MAX) + return (AH_FALSE); + + AR5K_REG_WRITE(AR5K_AR5212_DCU_GBL_IFS_SLOT, + ar5k_htoclock(slot_time, hal->ah_turbo)); + + return (AH_TRUE); +} + +u_int +ar5k_ar5212_getSlotTime(hal) + struct ath_hal *hal; +{ + return (ar5k_clocktoh(AR5K_REG_READ(AR5K_AR5212_DCU_GBL_IFS_SLOT) & + 0xffff, hal->ah_turbo)); +} + +HAL_BOOL +ar5k_ar5212_setAckTimeout(hal, timeout) + struct ath_hal *hal; + u_int timeout; +{ + if (ar5k_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_AR5212_TIME_OUT_ACK), + hal->ah_turbo) <= timeout) + return (AH_FALSE); + + AR5K_REG_WRITE_BITS(AR5K_AR5212_TIME_OUT, AR5K_AR5212_TIME_OUT_ACK, + ar5k_htoclock(timeout, hal->ah_turbo)); + + return (AH_TRUE); +} + +u_int +ar5k_ar5212_getAckTimeout(hal) + struct ath_hal *hal; +{ + return (ar5k_clocktoh(AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5212_TIME_OUT), + AR5K_AR5212_TIME_OUT_ACK), hal->ah_turbo)); +} + +HAL_BOOL +ar5k_ar5212_setCTSTimeout(hal, timeout) + struct ath_hal *hal; + u_int timeout; +{ + if (ar5k_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_AR5212_TIME_OUT_CTS), + hal->ah_turbo) <= timeout) + return (AH_FALSE); + + AR5K_REG_WRITE_BITS(AR5K_AR5212_TIME_OUT, AR5K_AR5212_TIME_OUT_CTS, + ar5k_htoclock(timeout, hal->ah_turbo)); + + return (AH_TRUE); +} + +u_int +ar5k_ar5212_getCTSTimeout(hal) + struct ath_hal *hal; +{ + return (ar5k_clocktoh(AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5212_TIME_OUT), + AR5K_AR5212_TIME_OUT_CTS), hal->ah_turbo)); +} + +/* + * Key table (WEP) functions + */ + +HAL_BOOL +ar5k_ar5212_isHwCipherSupported(hal, cipher) + struct ath_hal *hal; + HAL_CIPHER cipher; +{ + /* + * The AR5212 only supports WEP + */ + if (cipher == HAL_CIPHER_WEP) + return (AH_TRUE); + + return (AH_FALSE); +} + +u_int32_t +ar5k_ar5212_getKeyCacheSize(hal) + struct ath_hal *hal; +{ + return (AR5K_AR5212_KEYTABLE_SIZE); +} + +HAL_BOOL +ar5k_ar5212_resetKeyCacheEntry(hal, entry) + struct ath_hal *hal; + u_int16_t entry; +{ + int i; + + AR5K_ASSERT_ENTRY(entry, AR5K_AR5212_KEYTABLE_SIZE); + + for (i = 0; i < AR5K_AR5212_KEYCACHE_SIZE; i++) + AR5K_REG_WRITE(AR5K_AR5212_KEYTABLE(entry) + (i * 4), 0); + + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5212_isKeyCacheEntryValid(hal, entry) + struct ath_hal *hal; + u_int16_t entry; +{ + int offset; + + AR5K_ASSERT_ENTRY(entry, AR5K_AR5212_KEYTABLE_SIZE); + + /* + * Check the validation flag at the end of the entry + */ + offset = (AR5K_AR5212_KEYCACHE_SIZE - 1) * 4; + if (AR5K_REG_READ(AR5K_AR5212_KEYTABLE(entry) + offset) & + AR5K_AR5212_KEYTABLE_VALID) + return AH_TRUE; + + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5212_setKeyCacheEntry(hal, entry, keyval, mac, xor_notused) + struct ath_hal *hal; + u_int16_t entry; + const HAL_KEYVAL *keyval; + const u_int8_t *mac; + int xor_notused; +{ + int elements = AR5K_AR5212_KEYCACHE_SIZE - 2; + u_int32_t key_v[elements]; + int i, offset = 0; + + AR5K_ASSERT_ENTRY(entry, AR5K_AR5212_KEYTABLE_SIZE); + + /* + * Store the key type in the last field + */ + switch (keyval->wk_len) { + case 5: + key_v[elements - 1] = AR5K_AR5212_KEYTABLE_TYPE_40; + break; + + case 13: + key_v[elements - 1] = AR5K_AR5212_KEYTABLE_TYPE_104; + break; + + case 16: + key_v[elements - 1] = AR5K_AR5212_KEYTABLE_TYPE_128; + break; + + default: + /* Unsupported key length (not WEP40/104/128) */ + return (AH_FALSE); + } + + /* + * Write key cache entry + */ + for (i = 0; i < elements; i++) { + if (elements < 5) { + if (i % 2) { + key_v[i] = AR5K_LE_READ_2(keyval->wk_key + + offset) & 0xffff; + offset += 2; + } else { + key_v[i] = AR5K_LE_READ_4(keyval->wk_key + + offset); + offset += 4; + } + + if (i == 4 && keyval->wk_len <= 13) + key_v[i] &= 0xff; + } + + /* Write value */ + AR5K_REG_WRITE(AR5K_AR5212_KEYTABLE(entry) + (i * 4), key_v[i]); + } + + return (ar5k_ar5212_setKeyCacheEntryMac(hal, entry, mac)); +} + +HAL_BOOL +ar5k_ar5212_setKeyCacheEntryMac(hal, entry, mac) + struct ath_hal *hal; + u_int16_t entry; + const u_int8_t *mac; +{ + u_int32_t low_id, high_id; + int offset; + + /* + * Invalid entry (key table overflow) + */ + AR5K_ASSERT_ENTRY(entry, AR5K_AR5212_KEYTABLE_SIZE); + + offset = AR5K_AR5212_KEYCACHE_SIZE - 2; + + /* XXX big endian problems? */ + bcopy(mac, &low_id, 4); + bcopy(mac + 4, &high_id, 2); + + high_id = 0x0000ffff & htole32(high_id); + + AR5K_REG_WRITE(AR5K_AR5212_KEYTABLE(entry) + (offset++ * 4), + htole32(low_id)); + AR5K_REG_WRITE(AR5K_AR5212_KEYTABLE(entry) + (offset * 4), high_id); + + return (AH_TRUE); +} + +/* + * Power management functions + */ + +HAL_BOOL +ar5k_ar5212_setPowerMode(hal, mode, set_chip, sleep_duration) + struct ath_hal *hal; + HAL_POWER_MODE mode; + HAL_BOOL set_chip; + u_int16_t sleep_duration; +{ + int i; + + switch (mode) { + case HAL_PM_AUTO: + if (set_chip == AH_TRUE) { + AR5K_REG_WRITE(AR5K_AR5212_SCR, + AR5K_AR5212_SCR_SLE | sleep_duration); + } + break; + + case HAL_PM_FULL_SLEEP: + if (set_chip == AH_TRUE) { + AR5K_REG_WRITE(AR5K_AR5212_SCR, + AR5K_AR5212_SCR_SLE_SLP); + } + break; + + case HAL_PM_AWAKE: + if (set_chip == AH_FALSE) + goto commit; + + AR5K_REG_WRITE(AR5K_AR5212_SCR, AR5K_AR5212_SCR_SLE_WAKE); + + for (i = 5000; i > 0; i--) { + /* Check if the AR5212 did wake up */ + if ((AR5K_REG_READ(AR5K_AR5212_PCICFG) & + AR5K_AR5212_PCICFG_SPWR_DN) == 0) + break; + + /* Wait a bit and retry */ + AR5K_DELAY(200); + AR5K_REG_WRITE(AR5K_AR5212_SCR, + AR5K_AR5212_SCR_SLE_WAKE); + } + + /* Fail if the AR5212 didn't wake up */ + if (i <= 0) + return (AH_FALSE); + break; + + case HAL_PM_NETWORK_SLEEP: + case HAL_PM_UNDEFINED: + default: + return (AH_FALSE); + } + + commit: + hal->ah_power_mode = mode; + + AR5K_REG_DISABLE_BITS(AR5K_AR5212_STA_ID1, + AR5K_AR5212_STA_ID1_DEFAULT_ANTENNA); + AR5K_REG_ENABLE_BITS(AR5K_AR5212_STA_ID1, + AR5K_AR5212_STA_ID1_PWR_SV); + + return (AH_TRUE); +} + +HAL_POWER_MODE +ar5k_ar5212_getPowerMode(hal) + struct ath_hal *hal; +{ + return (hal->ah_power_mode); +} + +HAL_BOOL +ar5k_ar5212_queryPSPollSupport(hal) + struct ath_hal *hal; +{ + /* nope */ + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5212_initPSPoll(hal) + struct ath_hal *hal; +{ + /* + * Not used on the AR5212 + */ + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5212_enablePSPoll(hal, bssid, assoc_id) + struct ath_hal *hal; + u_int8_t *bssid; + u_int16_t assoc_id; +{ + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5212_disablePSPoll(hal) + struct ath_hal *hal; +{ + return (AH_FALSE); +} + +/* + * Beacon functions + */ + +void +ar5k_ar5212_beaconInit(hal, next_beacon, interval) + struct ath_hal *hal; + u_int32_t next_beacon; + u_int32_t interval; +{ + u_int32_t timer1, timer2, timer3; + + /* + * Set the additional timers by mode + */ + switch (hal->ah_op_mode) { + case HAL_M_STA: + timer1 = 0x0000ffff; + timer2 = 0x0007ffff; + break; + + default: + timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << + 0x00000003; + timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << + 0x00000003; + } + + timer3 = next_beacon + + (hal->ah_atim_window ? hal->ah_atim_window : 1); + + /* + * Enable all timers and set the beacon register + * (next beacon, DMA beacon, software beacon, ATIM window time) + */ + AR5K_REG_WRITE(AR5K_AR5212_TIMER0, next_beacon); + AR5K_REG_WRITE(AR5K_AR5212_TIMER1, timer1); + AR5K_REG_WRITE(AR5K_AR5212_TIMER2, timer2); + AR5K_REG_WRITE(AR5K_AR5212_TIMER3, timer3); + + AR5K_REG_WRITE(AR5K_AR5212_BEACON, interval & + (AR5K_AR5212_BEACON_PERIOD | AR5K_AR5212_BEACON_RESET_TSF | + AR5K_AR5212_BEACON_ENABLE)); +} + +void +ar5k_ar5212_setStationBeaconTimers(hal, state, tsf, dtim_count, cfp_count) + struct ath_hal *hal; + const HAL_BEACON_STATE *state; + u_int32_t tsf; + u_int32_t dtim_count; + u_int32_t cfp_count; + +{ + u_int32_t cfp_period, next_cfp; + + /* Return on an invalid beacon state */ + if (state->bs_interval > 0) + return; + + /* + * PCF support? + */ + if (state->bs_cfp_period > 0) { + /* Enable CFP mode and set the CFP and timer registers */ + cfp_period = state->bs_cfp_period * state->bs_dtim_period * + state->bs_interval; + next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * + state->bs_interval; + + AR5K_REG_DISABLE_BITS(AR5K_AR5212_STA_ID1, + AR5K_AR5212_STA_ID1_DEFAULT_ANTENNA | + AR5K_AR5212_STA_ID1_PCF); + AR5K_REG_WRITE(AR5K_AR5212_CFP_PERIOD, cfp_period); + AR5K_REG_WRITE(AR5K_AR5212_CFP_DUR, state->bs_cfp_max_duration); + AR5K_REG_WRITE(AR5K_AR5212_TIMER2, + (tsf + (next_cfp == 0 ? cfp_period : next_cfp)) << 3); + } else { + /* Disable PCF mode */ + AR5K_REG_DISABLE_BITS(AR5K_AR5212_STA_ID1, + AR5K_AR5212_STA_ID1_DEFAULT_ANTENNA | + AR5K_AR5212_STA_ID1_PCF); + } + + /* + * Enable the beacon timer register + */ + AR5K_REG_WRITE(AR5K_AR5212_TIMER0, state->bs_next_beacon); + + /* + * Start the beacon timers + */ + AR5K_REG_WRITE(AR5K_AR5212_BEACON, + (AR5K_REG_READ(AR5K_AR5212_BEACON) &~ + (AR5K_AR5212_BEACON_PERIOD | AR5K_AR5212_BEACON_TIM)) | + AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, + AR5K_AR5212_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, + AR5K_AR5212_BEACON_PERIOD)); + + /* + * Write new beacon miss threshold, if it appears to be valid + */ + if ((state->bs_bmiss_threshold > (AR5K_AR5212_RSSI_THR_BMISS >> + AR5K_AR5212_RSSI_THR_BMISS_S)) && + (state->bs_bmiss_threshold & 0x00007) != 0) { + AR5K_REG_WRITE_BITS(AR5K_AR5212_RSSI_THR_M, + AR5K_AR5212_RSSI_THR_BMISS, state->bs_bmiss_threshold); + } +} + +void +ar5k_ar5212_resetStationBeaconTimers(hal) + struct ath_hal *hal; +{ + /* + * Disable beacon timer + */ + AR5K_REG_WRITE(AR5K_AR5212_TIMER0, 0); + + /* + * Disable some beacon register values + */ + AR5K_REG_DISABLE_BITS(AR5K_AR5212_STA_ID1, + AR5K_AR5212_STA_ID1_DEFAULT_ANTENNA | AR5K_AR5212_STA_ID1_PCF); + AR5K_REG_WRITE(AR5K_AR5212_BEACON, AR5K_AR5212_BEACON_PERIOD); +} + +HAL_BOOL +ar5k_ar5212_waitForBeaconDone(hal, phys_addr) + struct ath_hal *hal; + bus_addr_t phys_addr; +{ + HAL_BOOL ret; + + /* + * Wait for beaconn queue to be done + */ + ret = ar5k_register_timeout(hal, + AR5K_AR5212_QCU_STS(HAL_TX_QUEUE_BEACON), + AR5K_AR5212_QCU_STS_FRMPENDCNT, 0, AH_FALSE); + + return (ret); +} + +/* + * Interrupt handling + */ + +HAL_BOOL +ar5k_ar5212_isInterruptPending(hal) + struct ath_hal *hal; +{ + return (AR5K_REG_READ(AR5K_AR5212_INTPEND) == 0 ? AH_FALSE : AH_TRUE); +} + +HAL_BOOL +ar5k_ar5212_getPendingInterrupts(hal, interrupt_mask) + struct ath_hal *hal; + u_int32_t *interrupt_mask; +{ + u_int32_t data; + + /* + * Read interrupt status from the Read-And-Clear shadow register + */ + data = AR5K_REG_READ(AR5K_AR5212_RAC_PISR); + + /* + * Get abstract interrupt mask (HAL-compatible) + */ + *interrupt_mask = (data & HAL_INT_COMMON) & hal->ah_imr; + + if (data == HAL_INT_NOCARD) + return (AH_FALSE); + + if (data & (AR5K_AR5212_PISR_RXOK | AR5K_AR5212_PISR_RXERR)) + *interrupt_mask |= HAL_INT_RX; + + if (data & (AR5K_AR5212_PISR_TXOK | AR5K_AR5212_PISR_TXERR)) + *interrupt_mask |= HAL_INT_TX; + + if (data & (AR5K_AR5212_PISR_HIUERR)) + *interrupt_mask |= HAL_INT_FATAL; + + /* + * Special interrupt handling (not catched by the driver) + */ + if (((*interrupt_mask) & AR5K_AR5212_PISR_RXPHY) && + hal->ah_radar.r_enabled == AH_TRUE) + ar5k_radar_alert(hal); + + return (AH_TRUE); +} + +u_int32_t +ar5k_ar5212_getInterrupts(hal) + struct ath_hal *hal; +{ + /* Return the interrupt mask stored previously */ + return (hal->ah_imr); +} + +HAL_INT +ar5k_ar5212_setInterrupts(hal, new_mask) + struct ath_hal *hal; + HAL_INT new_mask; +{ + HAL_INT old_mask, int_mask; + + /* + * Disable card interrupts to prevent any race conditions + * (they will be re-enabled afterwards). + */ + AR5K_REG_WRITE(AR5K_AR5212_IER, AR5K_AR5212_IER_DISABLE); + + old_mask = hal->ah_imr; + + /* + * Add additional, chipset-dependent interrupt mask flags + * and write them to the IMR (interrupt mask register). + */ + int_mask = new_mask & HAL_INT_COMMON; + + if (new_mask & HAL_INT_RX) + int_mask |= + AR5K_AR5212_PIMR_RXOK | + AR5K_AR5212_PIMR_RXERR | + AR5K_AR5212_PIMR_RXORN | + AR5K_AR5212_PIMR_RXDESC; + + if (new_mask & HAL_INT_TX) + int_mask |= + AR5K_AR5212_PIMR_TXOK | + AR5K_AR5212_PIMR_TXERR | + AR5K_AR5212_PIMR_TXDESC | + AR5K_AR5212_PIMR_TXURN; + + if (new_mask & HAL_INT_FATAL) { + int_mask |= AR5K_AR5212_PIMR_HIUERR; + AR5K_REG_ENABLE_BITS(AR5K_AR5212_SIMR2, + AR5K_AR5212_SIMR2_MCABT | + AR5K_AR5212_SIMR2_SSERR | + AR5K_AR5212_SIMR2_DPERR); + } + + if (hal->ah_op_mode & HAL_M_HOSTAP) { + int_mask |= AR5K_AR5212_PIMR_MIB; + } else { + int_mask &= ~AR5K_AR5212_PIMR_MIB; + } + + AR5K_REG_WRITE(AR5K_AR5212_PIMR, int_mask); + + /* Store new interrupt mask */ + hal->ah_imr = new_mask; + + /* ..re-enable interrupts */ + AR5K_REG_WRITE(AR5K_AR5212_IER, AR5K_AR5212_IER_ENABLE); + + return (old_mask); +} + +/* + * Misc internal functions + */ + +HAL_BOOL +ar5k_ar5212_get_capabilities(hal) + struct ath_hal *hal; +{ + u_int16_t ee_header; + + /* Capabilities stored in the EEPROM */ + ee_header = hal->ah_capabilities.cap_eeprom.ee_header; + + /* + * XXX The AR5212 tranceiver supports frequencies from 4920 to 6100GHz + * XXX and from 2312 to 2732GHz. There are problems with the current + * XXX ieee80211 implementation because the IEEE channel mapping + * XXX does not support negative channel numbers (2312MHz is channel + * XXX -19). Of course, this doesn't matter because these channels + * XXX are out of range but some regulation domains like MKK (Japan) + * XXX will support frequencies somewhere around 4.8GHz. + */ + + /* + * Set radio capabilities + */ + + if (AR5K_EEPROM_HDR_11A(ee_header)) { + hal->ah_capabilities.cap_range.range_5ghz_min = 5005; /* 4920 */ + hal->ah_capabilities.cap_range.range_5ghz_max = 6100; + + /* Set supported modes */ + hal->ah_capabilities.cap_mode = HAL_MODE_11A | HAL_MODE_TURBO; + } + + /* This chip will support 802.11b if the 2GHz radio is connected */ + if (AR5K_EEPROM_HDR_11B(ee_header) || AR5K_EEPROM_HDR_11G(ee_header)) { + hal->ah_capabilities.cap_range.range_2ghz_min = 2412; /* 2312 */ + hal->ah_capabilities.cap_range.range_2ghz_max = 2732; + hal->ah_capabilities.cap_mode |= HAL_MODE_11B; + + if (AR5K_EEPROM_HDR_11B(ee_header)) + hal->ah_capabilities.cap_mode |= HAL_MODE_11B; + if (AR5K_EEPROM_HDR_11G(ee_header)) + hal->ah_capabilities.cap_mode |= HAL_MODE_11G; + } + + /* GPIO */ + hal->ah_gpio_npins = AR5K_AR5212_NUM_GPIO; + + /* Set number of supported TX queues */ + hal->ah_capabilities.cap_queues.q_tx_num = AR5K_AR5212_TX_NUM_QUEUES; + + return (AH_TRUE); +} + +void +ar5k_ar5212_radar_alert(hal, enable) + struct ath_hal *hal; + HAL_BOOL enable; +{ + /* + * Enable radar detection + */ + AR5K_REG_WRITE(AR5K_AR5212_IER, AR5K_AR5212_IER_DISABLE); + + if (enable == AH_TRUE) { + AR5K_REG_WRITE(AR5K_AR5212_PHY_RADAR, + AR5K_AR5212_PHY_RADAR_ENABLE); + AR5K_REG_ENABLE_BITS(AR5K_AR5212_PIMR, + AR5K_AR5212_PIMR_RXPHY); + } else { + AR5K_REG_WRITE(AR5K_AR5212_PHY_RADAR, + AR5K_AR5212_PHY_RADAR_DISABLE); + AR5K_REG_DISABLE_BITS(AR5K_AR5212_PIMR, + AR5K_AR5212_PIMR_RXPHY); + } + + AR5K_REG_WRITE(AR5K_AR5212_IER, AR5K_AR5212_IER_ENABLE); +} + +/* + * EEPROM access functions + */ + +HAL_BOOL +ar5k_ar5212_eeprom_is_busy(hal) + struct ath_hal *hal; +{ + return (AR5K_REG_READ(AR5K_AR5212_CFG) & AR5K_AR5212_CFG_EEBS ? + AH_TRUE : AH_FALSE); +} + +int +ar5k_ar5212_eeprom_read(hal, offset, data) + struct ath_hal *hal; + u_int32_t offset; + u_int16_t *data; +{ + u_int32_t status, i; + + /* + * Initialize EEPROM access + */ + AR5K_REG_WRITE(AR5K_AR5212_EEPROM_BASE, (u_int8_t)offset); + AR5K_REG_ENABLE_BITS(AR5K_AR5212_EEPROM_CMD, + AR5K_AR5212_EEPROM_CMD_READ); + + for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { + status = AR5K_REG_READ(AR5K_AR5212_EEPROM_STATUS); + if (status & AR5K_AR5212_EEPROM_STAT_RDDONE) { + if (status & AR5K_AR5212_EEPROM_STAT_RDERR) + return (EIO); + *data = (u_int16_t) + (AR5K_REG_READ(AR5K_AR5212_EEPROM_DATA) & 0xffff); + return (0); + } + AR5K_DELAY(15); + } + + return (ETIMEDOUT); +} + +int +ar5k_ar5212_eeprom_write(hal, offset, data) + struct ath_hal *hal; + u_int32_t offset; + u_int16_t data; +{ + u_int32_t status, timeout; + + /* Enable eeprom access */ + AR5K_REG_ENABLE_BITS(AR5K_AR5212_EEPROM_CMD, + AR5K_AR5212_EEPROM_CMD_RESET); + AR5K_REG_ENABLE_BITS(AR5K_AR5212_EEPROM_CMD, + AR5K_AR5212_EEPROM_CMD_WRITE); + + /* + * Prime write pump + */ + AR5K_REG_WRITE(AR5K_AR5212_EEPROM_BASE, (u_int8_t)offset - 1); + + for (timeout = 10000; timeout > 0; timeout--) { + AR5K_DELAY(1); + status = AR5K_REG_READ(AR5K_AR5212_EEPROM_STATUS); + if (status & AR5K_AR5212_EEPROM_STAT_WRDONE) { + if (status & AR5K_AR5212_EEPROM_STAT_WRERR) + return (EIO); + return (0); + } + } + + return (ETIMEDOUT); +} + +/* + * TX power setup + */ + +HAL_BOOL +ar5k_ar5212_txpower(hal, channel, txpower) + struct ath_hal *hal; + HAL_CHANNEL *channel; + u_int txpower; +{ + if (txpower > AR5K_TUNE_MAX_TXPOWER) { + AR5K_PRINTF("invalid tx power: %u\n", txpower); + return (AH_FALSE); + } + +#ifdef notyet + for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { + AR5K_REG_WRITE(ah, AR5K_AR5212_PHY_PCDAC_TXPOWER(i), + ((((hal->ah_txpower.txp_pcdac[(i << 1) + 1] << 8) | 0xff) & + 0xffff) << 16) | (((hal->ah_txpower.txp_pcdac[i << 1] << 8) + | 0xff) & 0xffff)); + } + + AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE1, + AR5K_TXPOWER_OFDM(3, 24) | AR5K_TXPOWER_OFDM(2, 16) + | AR5K_TXPOWER_OFDM(1, 8) | AR5K_TXPOWER_OFDM(0, 0)); + + AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE2, + AR5K_TXPOWER_OFDM(7, 24) | AR5K_TXPOWER_OFDM(6, 16) + | AR5K_TXPOWER_OFDM(5, 8) | AR5K_TXPOWER_OFDM(4, 0)); + + AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE3, + AR5K_TXPOWER_CCK(10, 24) | AR5K_TXPOWER_CCK(9, 16) + | AR5K_TXPOWER_CCK(15, 8) | AR5K_TXPOWER_CCK(8, 0)); + + AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE4, + AR5K_TXPOWER_CCK(14, 24) | AR5K_TXPOWER_CCK(13, 16) + | AR5K_TXPOWER_CCK(12, 8) | AR5K_TXPOWER_CCK(11, 0)); +#endif + + if (hal->ah_txpower.txp_tpc == AH_TRUE) { + AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE_MAX, + AR5K_AR5212_PHY_TXPOWER_RATE_MAX_TPC_ENABLE | + AR5K_TUNE_MAX_TXPOWER); + } else { + AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE_MAX, + AR5K_AR5212_PHY_TXPOWER_RATE_MAX | + AR5K_TUNE_MAX_TXPOWER); + } + + return (AH_TRUE); +} diff --git a/sys/dev/ic/ar5212reg.h b/sys/dev/ic/ar5212reg.h new file mode 100644 index 00000000000..a11691ef111 --- /dev/null +++ b/sys/dev/ic/ar5212reg.h @@ -0,0 +1,1210 @@ +/* $OpenBSD: ar5212reg.h,v 1.1 2005/02/19 16:58:00 reyk Exp $ */ + +/* + * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Known registers of the Atheros AR5001 Wireless LAN chipsets + * (AR5212/AR5311). + */ + +#ifndef _AR5K_AR5212_REG_H +#define _AR5K_AR5212_REG_H + +/* + * Command register + */ +#define AR5K_AR5212_CR 0x0008 +#define AR5K_AR5212_CR_RXE 0x00000004 +#define AR5K_AR5212_CR_RXD 0x00000020 +#define AR5K_AR5212_CR_SWI 0x00000040 + +/* + * Receive queue descriptor pointer register + */ +#define AR5K_AR5212_RXDP 0x000c + +/* + * Configuration and status register + */ +#define AR5K_AR5212_CFG 0x0014 +#define AR5K_AR5212_CFG_SWTD 0x00000001 +#define AR5K_AR5212_CFG_SWTB 0x00000002 +#define AR5K_AR5212_CFG_SWRD 0x00000004 +#define AR5K_AR5212_CFG_SWRB 0x00000008 +#define AR5K_AR5212_CFG_SWRG 0x00000010 +#define AR5K_AR5212_CFG_ADHOC 0x00000020 +#define AR5K_AR5212_CFG_PHY_OK 0x00000100 +#define AR5K_AR5212_CFG_EEBS 0x00000200 +#define AR5K_AR5212_CFG_CLKGD 0x00000400 +#define AR5K_AR5212_CFG_PCI_THRES 0x00060000 +#define AR5K_AR5212_CFG_PCI_THRES_S 17 + +/* + * Interrupt enable register + */ +#define AR5K_AR5212_IER 0x0024 +#define AR5K_AR5212_IER_DISABLE 0x00000000 +#define AR5K_AR5212_IER_ENABLE 0x00000001 + +/* + * Transmit configuration register + */ +#define AR5K_AR5212_TXCFG 0x0030 +#define AR5K_AR5212_TXCFG_SDMAMR 0x00000007 +#define AR5K_AR5212_TXCFG_B_MODE 0x00000008 +#define AR5K_AR5212_TXCFG_TXFULL 0x000003f0 +#define AR5K_AR5212_TXCFG_TXFULL_S 4 +#define AR5K_AR5212_TXCFG_TXFULL_0B 0x00000000 +#define AR5K_AR5212_TXCFG_TXFULL_64B 0x00000010 +#define AR5K_AR5212_TXCFG_TXFULL_128B 0x00000020 +#define AR5K_AR5212_TXCFG_TXFULL_192B 0x00000030 +#define AR5K_AR5212_TXCFG_TXFULL_256B 0x00000040 +#define AR5K_AR5212_TXCFG_TXCONT_ENABLE 0x00000080 +#define AR5K_AR5212_TXCFG_JUMBO_TXE 0x00000400 +#define AR5K_AR5212_TXCFG_RTSRND 0x00001000 +#define AR5K_AR5212_TXCFG_FRMPAD_DIS 0x00002000 +#define AR5K_AR5212_TXCFG_RDY_DIS 0x00004000 + +/* + * Receive configuration register + */ +#define AR5K_AR5212_RXCFG 0x0034 +#define AR5K_AR5212_RXCFG_SDMAMW 0x00000007 +#define AR5K_AR5311_RXCFG_DEFAULT_ANTENNA 0x00000008 +#define AR5K_AR5212_RXCFG_ZLFDMA 0x00000010 +#define AR5K_AR5212_RXCFG_JUMBO_RXE 0x00000020 +#define AR5K_AR5212_RXCFG_JUMBO_WRAP 0x00000040 + +/* + * MIB control register + */ +#define AR5K_AR5212_MIBC 0x0040 +#define AR5K_AR5212_MIBC_COW 0x00000001 +#define AR5K_AR5212_MIBC_FMC 0x00000002 +#define AR5K_AR5212_MIBC_CMC 0x00000004 +#define AR5K_AR5212_MIBC_MCS 0x00000008 + +/* + * Timeout prescale register + */ +#define AR5K_AR5212_TOPS 0x0044 +#define AR5K_AR5212_TOPS_M 0x0000ffff + +/* + * Receive timeout register (no frame received) + */ +#define AR5K_AR5212_RXNOFRM 0x0048 +#define AR5K_AR5212_RXNOFRM_M 0x000003ff + +/* + * Transmit timeout register (no frame sent) + */ +#define AR5K_AR5212_TXNOFRM 0x004c +#define AR5K_AR5212_TXNOFRM_M 0x000003ff +#define AR5K_AR5212_TXNOFRM_QCU 0x000ffc00 + +/* + * Receive frame gap timeout register + */ +#define AR5K_AR5212_RPGTO 0x0050 +#define AR5K_AR5212_RPGTO_M 0x000003ff + +/* + * Receive frame count limit register + */ +#define AR5K_AR5212_RFCNT 0x0054 +#define AR5K_AR5212_RFCNT_M 0x0000001f + +/* + * Misc settings register + */ +#define AR5K_AR5212_MISC 0x0058 +#define AR5K_AR5212_MISC_DMA_OBS_M 0x000001e0 +#define AR5K_AR5212_MISC_DMA_OBS_S 5 +#define AR5K_AR5212_MISC_MISC_OBS_M 0x00000e00 +#define AR5K_AR5212_MISC_MISC_OBS_S 9 +#define AR5K_AR5212_MISC_MAC_OBS_LSB_M 0x00007000 +#define AR5K_AR5212_MISC_MAC_OBS_LSB_S 12 +#define AR5K_AR5212_MISC_MAC_OBS_MSB_M 0x00038000 +#define AR5K_AR5212_MISC_MAC_OBS_MSB_S 15 + +/* + * Primary interrupt status register + */ +#define AR5K_AR5212_PISR 0x0080 +#define AR5K_AR5212_PISR_RXOK 0x00000001 +#define AR5K_AR5212_PISR_RXDESC 0x00000002 +#define AR5K_AR5212_PISR_RXERR 0x00000004 +#define AR5K_AR5212_PISR_RXNOFRM 0x00000008 +#define AR5K_AR5212_PISR_RXEOL 0x00000010 +#define AR5K_AR5212_PISR_RXORN 0x00000020 +#define AR5K_AR5212_PISR_TXOK 0x00000040 +#define AR5K_AR5212_PISR_TXDESC 0x00000080 +#define AR5K_AR5212_PISR_TXERR 0x00000100 +#define AR5K_AR5212_PISR_TXNOFRM 0x00000200 +#define AR5K_AR5212_PISR_TXEOL 0x00000400 +#define AR5K_AR5212_PISR_TXURN 0x00000800 +#define AR5K_AR5212_PISR_MIB 0x00001000 +#define AR5K_AR5212_PISR_SWI 0x00002000 +#define AR5K_AR5212_PISR_RXPHY 0x00004000 +#define AR5K_AR5212_PISR_RXKCM 0x00008000 +#define AR5K_AR5212_PISR_SWBA 0x00010000 +#define AR5K_AR5212_PISR_BRSSI 0x00020000 +#define AR5K_AR5212_PISR_BMISS 0x00040000 +#define AR5K_AR5212_PISR_HIUERR 0x00080000 +#define AR5K_AR5212_PISR_BNR 0x00100000 +#define AR5K_AR5212_PISR_RXCHIRP 0x00200000 +#define AR5K_AR5212_PISR_TIM 0x00800000 +#define AR5K_AR5212_PISR_BCNMISC 0x00800000 +#define AR5K_AR5212_PISR_GPIO 0x01000000 +#define AR5K_AR5212_PISR_QCBRORN 0x02000000 +#define AR5K_AR5212_PISR_QCBRURN 0x04000000 +#define AR5K_AR5212_PISR_QTRIG 0x08000000 + +/* + * Secondary interrupt status registers (0 - 4) + */ +#define AR5K_AR5212_SISR0 0x0084 +#define AR5K_AR5212_SISR0_QCU_TXOK 0x000003ff +#define AR5K_AR5212_SISR0_QCU_TXDESC 0x03ff0000 + +#define AR5K_AR5212_SISR1 0x0088 +#define AR5K_AR5212_SISR1_QCU_TXERR 0x000003ff +#define AR5K_AR5212_SISR1_QCU_TXEOL 0x03ff0000 + +#define AR5K_AR5212_SISR2 0x008c +#define AR5K_AR5212_SISR2_QCU_TXURN 0x000003ff +#define AR5K_AR5212_SISR2_MCABT 0x00100000 +#define AR5K_AR5212_SISR2_SSERR 0x00200000 +#define AR5K_AR5212_SISR2_DPERR 0x00400000 +#define AR5K_AR5212_SISR2_TIM 0x01000000 +#define AR5K_AR5212_SISR2_CAB_END 0x02000000 +#define AR5K_AR5212_SISR2_DTIM_SYNC 0x04000000 +#define AR5K_AR5212_SISR2_BCN_TIMEOUT 0x08000000 +#define AR5K_AR5212_SISR2_CAB_TIMEOUT 0x10000000 +#define AR5K_AR5212_SISR2_DTIM 0x20000000 + +#define AR5K_AR5212_SISR3 0x0090 +#define AR5K_AR5212_SISR3_QCBRORN 0x000003ff +#define AR5K_AR5212_SISR3_QCBRURN 0x03ff0000 + +#define AR5K_AR5212_SISR4 0x0094 +#define AR5K_AR5212_SISR4_QTRIG 0x000003ff + +/* + * Shadow read-and-clear interrupt status registers + */ +#define AR5K_AR5212_RAC_PISR 0x00c0 +#define AR5K_AR5212_RAC_SISR0 0x00c4 +#define AR5K_AR5212_RAC_SISR1 0x00c8 +#define AR5K_AR5212_RAC_SISR2 0x00cc +#define AR5K_AR5212_RAC_SISR3 0c00d0 +#define AR5K_AR5212_RAC_SISR4 0c00d4 + +/* + * Primary interrupt mask register + */ +#define AR5K_AR5212_PIMR 0x00a0 +#define AR5K_AR5212_PIMR_RXOK 0x00000001 +#define AR5K_AR5212_PIMR_RXDESC 0x00000002 +#define AR5K_AR5212_PIMR_RXERR 0x00000004 +#define AR5K_AR5212_PIMR_RXNOFRM 0x00000008 +#define AR5K_AR5212_PIMR_RXEOL 0x00000010 +#define AR5K_AR5212_PIMR_RXORN 0x00000020 +#define AR5K_AR5212_PIMR_TXOK 0x00000040 +#define AR5K_AR5212_PIMR_TXDESC 0x00000080 +#define AR5K_AR5212_PIMR_TXERR 0x00000100 +#define AR5K_AR5212_PIMR_TXNOFRM 0x00000200 +#define AR5K_AR5212_PIMR_TXEOL 0x00000400 +#define AR5K_AR5212_PIMR_TXURN 0x00000800 +#define AR5K_AR5212_PIMR_MIB 0x00001000 +#define AR5K_AR5212_PIMR_SWI 0x00002000 +#define AR5K_AR5212_PIMR_RXPHY 0x00004000 +#define AR5K_AR5212_PIMR_RXKCM 0x00008000 +#define AR5K_AR5212_PIMR_SWBA 0x00010000 +#define AR5K_AR5212_PIMR_BRSSI 0x00020000 +#define AR5K_AR5212_PIMR_BMISS 0x00040000 +#define AR5K_AR5212_PIMR_HIUERR 0x00080000 +#define AR5K_AR5212_PIMR_BNR 0x00100000 +#define AR5K_AR5212_PIMR_RXCHIRP 0x00200000 +#define AR5K_AR5212_PIMR_TIM 0x00800000 +#define AR5K_AR5212_PIMR_BCNMISC 0x00800000 +#define AR5K_AR5212_PIMR_GPIO 0x01000000 +#define AR5K_AR5212_PIMR_QCBRORN 0x02000000 +#define AR5K_AR5212_PIMR_QCBRURN 0x04000000 +#define AR5K_AR5212_PIMR_QTRIG 0x08000000 + +/* + * Secondary interrupt mask registers (0 - 4) + */ +#define AR5K_AR5212_SIMR0 0x00a4 +#define AR5K_AR5212_SIMR0_QCU_TXOK 0x000003ff +#define AR5K_AR5212_SIMR0_QCU_TXOK_S 0 +#define AR5K_AR5212_SIMR0_QCU_TXDESC 0x03ff0000 +#define AR5K_AR5212_SIMR0_QCU_TXDESC_S 16 + +#define AR5K_AR5212_SIMR1 0x00a8 +#define AR5K_AR5212_SIMR1_QCU_TXERR 0x000003ff +#define AR5K_AR5212_SIMR1_QCU_TXERR_S 0 +#define AR5K_AR5212_SIMR1_QCU_TXEOL 0x03ff0000 +#define AR5K_AR5212_SIMR1_QCU_TXEOL_S 16 + +#define AR5K_AR5212_SIMR2 0x00ac +#define AR5K_AR5212_SIMR2_QCU_TXURN 0x000003ff +#define AR5K_AR5212_SIMR2_QCU_TXURN_S 0 +#define AR5K_AR5212_SIMR2_MCABT 0x00100000 +#define AR5K_AR5212_SIMR2_SSERR 0x00200000 +#define AR5K_AR5212_SIMR2_DPERR 0x00400000 +#define AR5K_AR5212_SIMR2_TIM 0x01000000 +#define AR5K_AR5212_SIMR2_CAB_END 0x02000000 +#define AR5K_AR5212_SIMR2_DTIM_SYNC 0x04000000 +#define AR5K_AR5212_SIMR2_BCN_TIMEOUT 0x08000000 +#define AR5K_AR5212_SIMR2_CAB_TIMEOUT 0x10000000 +#define AR5K_AR5212_SIMR2_DTIM 0x20000000 + +#define AR5K_AR5212_SIMR3 0x00b0 +#define AR5K_AR5212_SIMR3_QCBRORN 0x000003ff +#define AR5K_AR5212_SIMR3_QCBRORN_S 0 +#define AR5K_AR5212_SIMR3_QCBRURN 0x03ff0000 +#define AR5K_AR5212_SIMR3_QCBRURN_S 16 + +#define AR5K_AR5212_SIMR4 0x00b4 +#define AR5K_AR5212_SIMR4_QTRIG 0x000003ff +#define AR5K_AR5212_SIMR4_QTRIG_S 0 + +/* + * Decompression mask registers + */ +#define AR5K_AR5212_DCM_ADDR 0x0400 +#define AR5K_AR5212_DCM_DATA 0x0404 + +/* + * Decompression configuration registers + */ +#define AR5K_AR5212_DCCFG 0x0420 + +/* + * Compression configuration registers + */ +#define AR5K_AR5212_CCFG 0x0600 +#define AR5K_AR5212_CCFG_CUP 0x0604 + +/* + * Compression performance counter registers + */ +#define AR5K_AR5212_CPC0 0x0610 +#define AR5K_AR5212_CPC1 0x0614 +#define AR5K_AR5212_CPC2 0x0618 +#define AR5K_AR5212_CPC3 0x061c +#define AR5K_AR5212_CPCORN 0x0620 + +/* + * Queue control unit (QCU) registers (0 - 9) + */ +#define AR5K_AR5212_QCU(_n, _a) (((_n) << 2) + _a) + +/* + * QCU Transmit descriptor pointer registers + */ +#define AR5K_AR5212_QCU_TXDP(_n) AR5K_AR5212_QCU(_n, 0x0800) + +/* + * QCU Transmit enable register + */ +#define AR5K_AR5212_QCU_TXE 0x0840 + +/* + * QCU Transmit disable register + */ +#define AR5K_AR5212_QCU_TXD 0x0880 + +/* + * QCU CBR configuration registers + */ +#define AR5K_AR5212_QCU_CBRCFG(_n) AR5K_AR5212_QCU(_n, 0x08c0) +#define AR5K_AR5212_QCU_CBRCFG_INTVAL 0x00ffffff +#define AR5K_AR5212_QCU_CBRCFG_INTVAL_S 0 +#define AR5K_AR5212_QCU_CBRCFG_ORN_THRES 0xff000000 +#define AR5K_AR5212_QCU_CBRCFG_ORN_THRES_S 24 + +/* + * QCU Ready time configuration registers + */ +#define AR5K_AR5212_QCU_RDYTIMECFG(_n) AR5K_AR5212_QCU(_n, 0x0900) +#define AR5K_AR5212_QCU_RDYTIMECFG_INTVAL 0x00ffffff +#define AR5K_AR5212_QCU_RDYTIMECFG_INTVAL_S 0 +#define AR5K_AR5212_QCU_RDYTIMECFG_DURATION 0x00ffffff +#define AR5K_AR5212_QCU_RDYTIMECFG_ENABLE 0x01000000 + +/* + * QCU one shot arm set registers + */ +#define AR5K_AR5212_QCU_ONESHOTARMS(_n) AR5K_AR5212_QCU(_n, 0x0940) +#define AR5K_AR5212_QCU_ONESHOTARMS_M 0x0000ffff + +/* + * QCU one shot arm clear registers + */ +#define AR5K_AR5212_QCU_ONESHOTARMC(_n) AR5K_AR5212_QCU(_n, 0x0980) +#define AR5K_AR5212_QCU_ONESHOTARMC_M 0x0000ffff + +/* + * QCU misc registers + */ +#define AR5K_AR5212_QCU_MISC(_n) AR5K_AR5212_QCU(_n, 0x09c0) +#define AR5K_AR5212_QCU_MISC_FRSHED_M 0x0000000f +#define AR5K_AR5212_QCU_MISC_FRSHED_ASAP 0 +#define AR5K_AR5212_QCU_MISC_FRSHED_CBR 1 +#define AR5K_AR5212_QCU_MISC_FRSHED_DBA_GT 2 +#define AR5K_AR5212_QCU_MISC_FRSHED_TIM_GT 3 +#define AR5K_AR5212_QCU_MISC_FRSHED_BCN_SENT_GT 4 +#define AR5K_AR5212_QCU_MISC_ONESHOT_ENABLE 0x00000010 +#define AR5K_AR5212_QCU_MISC_CBREXP 0x00000020 +#define AR5K_AR5212_QCU_MISC_CBREXP_BCN 0x00000040 +#define AR5K_AR5212_QCU_MISC_BCN_ENABLE 0x00000080 +#define AR5K_AR5212_QCU_MISC_CBR_THRES_ENABLE 0x00000100 +#define AR5K_AR5212_QCU_MISC_TXE 0x00000200 +#define AR5K_AR5212_QCU_MISC_CBR 0x00000400 +#define AR5K_AR5212_QCU_MISC_DCU_EARLY 0x00000800 + +/* + * QCU status registers + */ +#define AR5K_AR5212_QCU_STS(_n) AR5K_AR5212_QCU(_n, 0x0a00) +#define AR5K_AR5212_QCU_STS_FRMPENDCNT 0x00000003 +#define AR5K_AR5212_QCU_STS_CBREXPCNT 0x0000ff00 + +/* + * QCU ready time shutdown register + */ +#define AR5K_AR5212_QCU_RDYTIMESHDN 0x0a40 +#define AR5K_AR5212_QCU_RDYTIMESHDN_M 0x000003ff + +/* + * QCU compression buffer base registers + */ +#define AR5K_AR5212_QCU_CBB_SELECT 0x0b00 +#define AR5K_AR5212_QCU_CBB_ADDR 0x0b04 + +/* + * QCU compression buffer configuration register + */ +#define AR5K_AR5212_QCU_CBCFG 0x0b08 + +/* + * DCF control unit (DCU) registers (0 - 9) + */ +#define AR5K_AR5212_DCU(_n, _a) AR5K_AR5212_QCU(_n, _a) + +/* + * DCU QCU mask registers + */ +#define AR5K_AR5212_DCU_QCUMASK(_n) AR5K_AR5212_DCU(_n, 0x1000) +#define AR5K_AR5212_DCU_QCUMASK_M 0x000003ff + +/* + * DCU local IFS settings register + */ +#define AR5K_AR5212_DCU_LCL_IFS(_n) AR5K_AR5212_DCU(_n, 0x1040) +#define AR5K_AR5212_DCU_LCL_IFS_CW_MIN 0x000003ff +#define AR5K_AR5212_DCU_LCL_IFS_CW_MIN_S 0 +#define AR5K_AR5212_DCU_LCL_IFS_CW_MAX 0x000ffc00 +#define AR5K_AR5212_DCU_LCL_IFS_CW_MAX_S 10 +#define AR5K_AR5212_DCU_LCL_IFS_AIFS 0x0ff00000 +#define AR5K_AR5212_DCU_LCL_IFS_AIFS_S 20 + +/* + * DCU retry limit registers + */ +#define AR5K_AR5212_DCU_RETRY_LMT(_n) AR5K_AR5212_DCU(_n, 0x1080) +#define AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY 0x0000000f +#define AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY_S 0 +#define AR5K_AR5212_DCU_RETRY_LMT_LG_RETRY 0x000000f0 +#define AR5K_AR5212_DCU_RETRY_LMT_LG_RETRY_S 4 +#define AR5K_AR5212_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 +#define AR5K_AR5212_DCU_RETRY_LMT_SSH_RETRY_S 8 +#define AR5K_AR5212_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 +#define AR5K_AR5212_DCU_RETRY_LMT_SLG_RETRY_S 14 + +/* + * DCU channel time registers + */ +#define AR5K_AR5212_DCU_CHAN_TIME(_n) AR5K_AR5212_DCU(_n, 0x10c0) +#define AR5K_AR5212_DCU_CHAN_TIME_DUR 0x000fffff +#define AR5K_AR5212_DCU_CHAN_TIME_DUR_S 0 +#define AR5K_AR5212_DCU_CHAN_TIME_ENABLE 0x00100000 + +/* + * DCU misc registers + */ +#define AR5K_AR5212_DCU_MISC(_n) AR5K_AR5212_DCU(_n, 0x1100) +#define AR5K_AR5212_DCU_MISC_BACKOFF 0x000007ff +#define AR5K_AR5212_DCU_MISC_BACKOFF_FRAG 0x00000200 +#define AR5K_AR5212_DCU_MISC_HCFPOLL_ENABLE 0x00000800 +#define AR5K_AR5212_DCU_MISC_BACKOFF_PERSIST 0x00001000 +#define AR5K_AR5212_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 +#define AR5K_AR5212_DCU_MISC_VIRTCOL 0x0000c000 +#define AR5K_AR5212_DCU_MISC_VIRTCOL_NORMAL 0 +#define AR5K_AR5212_DCU_MISC_VIRTCOL_MODIFIED 1 +#define AR5K_AR5212_DCU_MISC_VIRTCOL_IGNORE 2 +#define AR5K_AR5212_DCU_MISC_BCN_ENABLE 0x00010000 +#define AR5K_AR5212_DCU_MISC_ARBLOCK_CTL 0x00060000 +#define AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_S 17 +#define AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_NONE 0 +#define AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_INTFRM 1 +#define AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 +#define AR5K_AR5212_DCU_MISC_ARBLOCK_IGNORE 0x00080000 +#define AR5K_AR5212_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 +#define AR5K_AR5212_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 +#define AR5K_AR5212_DCU_MISC_VIRT_COLL_POLICY 0x00400000 +#define AR5K_AR5212_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 +#define AR5K_AR5212_DCU_MISC_SEQNUM_CTL 0x01000000 + +/* + * DCU frame sequence number registers + */ +#define AR5K_AR5212_DCU_SEQNUM(_n) AR5K_AR5212_DCU(_n, 0x1140) +#define AR5K_AR5212_DCU_SEQNUM_M 0x00000fff +/* + * DCU global IFS SIFS registers + */ +#define AR5K_AR5212_DCU_GBL_IFS_SIFS 0x1030 +#define AR5K_AR5212_DCU_GBL_IFS_SIFS_M 0x0000ffff + +/* + * DCU global IFS slot interval registers + */ +#define AR5K_AR5212_DCU_GBL_IFS_SLOT 0x1070 +#define AR5K_AR5212_DCU_GBL_IFS_SLOT_M 0x0000ffff + +/* + * DCU global IFS EIFS registers + */ +#define AR5K_AR5212_DCU_GBL_IFS_EIFS 0x10b0 +#define AR5K_AR5212_DCU_GBL_IFS_EIFS_M 0x0000ffff + +/* + * DCU global IFS misc registers + */ +#define AR5K_AR5212_DCU_GBL_IFS_MISC 0x10f0 +#define AR5K_AR5212_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 +#define AR5K_AR5212_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 +#define AR5K_AR5212_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 +#define AR5K_AR5212_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 +#define AR5K_AR5212_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 + +/* + * DCU frame prefetch control register + */ +#define AR5K_AR5212_DCU_FP 0x1230 + +/* + * DCU transmit pause control/status register + */ +#define AR5K_AR5212_DCU_TXP 0x1270 +#define AR5K_AR5212_DCU_TXP_M 0x000003ff +#define AR5K_AR5212_DCU_TXP_STATUS 0x00010000 + +/* + * DCU transmit filter register + */ +#define AR5K_AR5212_DCU_TX_FILTER 0x1038 + +/* + * DCU clear transmit filter register + */ +#define AR5K_AR5212_DCU_TX_FILTER_CLR 0x143c + +/* + * DCU set transmit filter register + */ +#define AR5K_AR5212_DCU_TX_FILTER_SET 0x147c + +/* + * DMA size definitions + */ +typedef enum { + AR5K_AR5212_DMASIZE_4B = 0, + AR5K_AR5212_DMASIZE_8B, + AR5K_AR5212_DMASIZE_16B, + AR5K_AR5212_DMASIZE_32B, + AR5K_AR5212_DMASIZE_64B, + AR5K_AR5212_DMASIZE_128B, + AR5K_AR5212_DMASIZE_256B, + AR5K_AR5212_DMASIZE_512B +} ar5k_ar5212_dmasize_t; + +/* + * Reset control register + */ +#define AR5K_AR5212_RC 0x4000 +#define AR5K_AR5212_RC_PCU 0x00000001 +#define AR5K_AR5212_RC_BB 0x00000002 +#define AR5K_AR5212_RC_PCI 0x00000010 +#define AR5K_AR5212_RC_CHIP ( \ + AR5K_AR5212_RC_PCU | AR5K_AR5212_RC_BB | AR5K_AR5212_RC_PCI \ +) + +/* + * Sleep control register + */ +#define AR5K_AR5212_SCR 0x4004 +#define AR5K_AR5212_SCR_SLDUR 0x0000ffff +#define AR5K_AR5212_SCR_SLE 0x00030000 +#define AR5K_AR5212_SCR_SLE_S 16 +#define AR5K_AR5212_SCR_SLE_WAKE 0x00000000 +#define AR5K_AR5212_SCR_SLE_SLP 0x00010000 +#define AR5K_AR5212_SCR_SLE_ALLOW 0x00020000 +#define AR5K_AR5212_SCR_SLE_UNITS 0x00000008 + +/* + * Interrupt pending register + */ +#define AR5K_AR5212_INTPEND 0x4008 +#define AR5K_AR5212_INTPEND_M 0x00000001 + +/* + * Sleep force register + */ +#define AR5K_AR5212_SFR 0x400c +#define AR5K_AR5212_SFR_M 0x00000001 + +/* + * PCI configuration register + */ +#define AR5K_AR5212_PCICFG 0x4010 +#define AR5K_AR5212_PCICFG_CLKRUNEN 0x00000004 +#define AR5K_AR5212_PCICFG_EESIZE 0x00000018 +#define AR5K_AR5212_PCICFG_EESIZE_S 3 +#define AR5K_AR5212_PCICFG_EESIZE_4K 0 +#define AR5K_AR5212_PCICFG_EESIZE_8K 1 +#define AR5K_AR5212_PCICFG_EESIZE_16K 2 +#define AR5K_AR5212_PCICFG_EESIZE_FAIL 3 +#define AR5K_AR5212_PCICFG_LED 0x00000060 +#define AR5K_AR5212_PCICFG_LED_NONE 0x00000000 +#define AR5K_AR5212_PCICFG_LED_PEND 0x00000020 +#define AR5K_AR5212_PCICFG_LED_ASSOC 0x00000040 +#define AR5K_AR5212_PCICFG_BUS_SEL 0x00000380 +#define AR5K_AR5212_PCICFG_CBEFIX_DIS 0x00000400 +#define AR5K_AR5212_PCICFG_SL_INTEN 0x00000800 +#define AR5K_AR5212_PCICFG_SL_INPEN 0x00002800 +#define AR5K_AR5212_PCICFG_SPWR_DN 0x00010000 +#define AR5K_AR5212_PCICFG_LEDMODE 0x000e0000 +#define AR5K_AR5212_PCICFG_LEDMODE_PROP 0x00000000 +#define AR5K_AR5212_PCICFG_LEDMODE_PROM 0x00020000 +#define AR5K_AR5212_PCICFG_LEDMODE_PWR 0x00040000 +#define AR5K_AR5212_PCICFG_LEDMODE_RAND 0x00060000 +#define AR5K_AR5212_PCICFG_LEDBLINK 0x00700000 +#define AR5K_AR5212_PCICFG_LEDBLINK_S 20 +#define AR5K_AR5212_PCICFG_LEDSLOW 0x00800000 + +/* + * "General Purpose Input/Output" (GPIO) control register + */ +#define AR5K_AR5212_GPIOCR 0x4014 +#define AR5K_AR5212_GPIOCR_INT_ENA 0x00008000 +#define AR5K_AR5212_GPIOCR_INT_SELL 0x00000000 +#define AR5K_AR5212_GPIOCR_INT_SELH 0x00010000 +#define AR5K_AR5212_GPIOCR_NONE(n) (0 << ((n) * 2)) +#define AR5K_AR5212_GPIOCR_OUT0(n) (1 << ((n) * 2)) +#define AR5K_AR5212_GPIOCR_OUT1(n) (2 << ((n) * 2)) +#define AR5K_AR5212_GPIOCR_ALL(n) (3 << ((n) * 2)) +#define AR5K_AR5212_GPIOCR_INT_SEL(n) ((n) << 12) + +#define AR5K_AR5212_NUM_GPIO 6 + +/* + * "General Purpose Input/Output" (GPIO) data output register + */ +#define AR5K_AR5212_GPIODO 0x4018 + +/* + * "General Purpose Input/Output" (GPIO) data input register + */ +#define AR5K_AR5212_GPIODI 0x401c +#define AR5K_AR5212_GPIODI_M 0x0000002f + +/* + * Silicon revision register + */ +#define AR5K_AR5212_SREV 0x4020 +#define AR5K_AR5212_SREV_M 0x000000ff +#define AR5K_AR5212_SREV_REVISION 0x0000000f +#define AR5K_AR5212_SREV_VERSION 0x000000f0 + +/* + * EEPROM access registers + */ +#define AR5K_AR5212_EEPROM_BASE 0x6000 +#define AR5K_AR5212_EEPROM_DATA 0x6004 +#define AR5K_AR5212_EEPROM_CMD 0x6008 +#define AR5K_AR5212_EEPROM_CMD_READ 0x00000001 +#define AR5K_AR5212_EEPROM_CMD_WRITE 0x00000002 +#define AR5K_AR5212_EEPROM_CMD_RESET 0x00000004 +#define AR5K_AR5212_EEPROM_STATUS 0x600c +#define AR5K_AR5212_EEPROM_STAT_RDERR 0x00000001 +#define AR5K_AR5212_EEPROM_STAT_RDDONE 0x00000002 +#define AR5K_AR5212_EEPROM_STAT_WRERR 0x00000004 +#define AR5K_AR5212_EEPROM_STAT_WRDONE 0x00000008 +#define AR5K_AR5212_EEPROM_CFG 0x6010 + +/* + * PCU registers + */ + +#define AR5K_AR5212_PCU_MIN 0x8000 +#define AR5K_AR5212_PCU_MAX 0x8fff + +/* + * First station id register (MAC address in lower 32 bits) + */ +#define AR5K_AR5212_STA_ID0 0x8000 + +/* + * Second station id register (MAC address in upper 16 bits) + */ +#define AR5K_AR5212_STA_ID1 0x8004 +#define AR5K_AR5212_STA_ID1_AP 0x00010000 +#define AR5K_AR5212_STA_ID1_ADHOC 0x00020000 +#define AR5K_AR5212_STA_ID1_PWR_SV 0x00040000 +#define AR5K_AR5212_STA_ID1_NO_KEYSRCH 0x00080000 +#define AR5K_AR5212_STA_ID1_PCF 0x00100000 +#define AR5K_AR5212_STA_ID1_DEFAULT_ANTENNA 0x00200000 +#define AR5K_AR5212_STA_ID1_DESC_ANTENNA 0x00400000 +#define AR5K_AR5212_STA_ID1_RTS_DEFAULT_ANTENNA 0x00800000 +#define AR5K_AR5212_STA_ID1_ACKCTS_6MB 0x01000000 +#define AR5K_AR5212_STA_ID1_BASE_RATE_11B 0x02000000 + +/* + * First BSSID register (MAC address, lower 32bits) + */ +#define AR5K_AR5212_BSS_ID0 0x8008 + +/* + * Second BSSID register (MAC address in upper 16 bits) + * + * AID: Association ID + */ +#define AR5K_AR5212_BSS_ID1 0x800c +#define AR5K_AR5212_BSS_ID1_AID 0xffff0000 +#define AR5K_AR5212_BSS_ID1_AID_S 16 + +/* + * Backoff slot time register + */ +#define AR5K_AR5212_SLOT_TIME 0x8010 + +/* + * ACK/CTS timeout register + */ +#define AR5K_AR5212_TIME_OUT 0x8014 +#define AR5K_AR5212_TIME_OUT_ACK 0x00001fff +#define AR5K_AR5212_TIME_OUT_ACK_S 0 +#define AR5K_AR5212_TIME_OUT_CTS 0x1fff0000 +#define AR5K_AR5212_TIME_OUT_CTS_S 16 + +/* + * RSSI threshold register + */ +#define AR5K_AR5212_RSSI_THR 0x8018 +#define AR5K_AR5212_RSSI_THR_M 0x000000ff +#define AR5K_AR5212_RSSI_THR_BMISS 0x0000ff00 +#define AR5K_AR5212_RSSI_THR_BMISS_S 8 + +/* + * Transmit latency register + */ +#define AR5K_AR5212_USEC 0x801c +#define AR5K_AR5212_USEC_1 0x0000007f +#define AR5K_AR5212_USEC_1_S 0 +#define AR5K_AR5212_USEC_32 0x00003f80 +#define AR5K_AR5212_USEC_32_S 7 +#define AR5K_AR5212_USEC_TX_LATENCY 0x007fc000 +#define AR5K_AR5212_USEC_TX_LATENCY_S 14 +#define AR5K_AR5212_USEC_RX_LATENCY 0x1f800000 +#define AR5K_AR5212_USEC_RX_LATENCY_S 23 +#define AR5K_AR5311_USEC_TX_LATENCY 0x000fc000 +#define AR5K_AR5311_USEC_TX_LATENCY_S 14 +#define AR5K_AR5311_USEC_RX_LATENCY 0x03f00000 +#define AR5K_AR5311_USEC_RX_LATENCY_S 20 + +/* + * PCU beacon control register + */ +#define AR5K_AR5212_BEACON 0x8020 +#define AR5K_AR5212_BEACON_PERIOD 0x0000ffff +#define AR5K_AR5212_BEACON_PERIOD_S 0 +#define AR5K_AR5212_BEACON_TIM 0x007f0000 +#define AR5K_AR5212_BEACON_TIM_S 16 +#define AR5K_AR5212_BEACON_ENABLE 0x00800000 +#define AR5K_AR5212_BEACON_RESET_TSF 0x01000000 + +/* + * CFP period register + */ +#define AR5K_AR5212_CFP_PERIOD 0x8024 + +/* + * Next beacon time register + */ +#define AR5K_AR5212_TIMER0 0x8028 + +/* + * Next DMA beacon alert register + */ +#define AR5K_AR5212_TIMER1 0x802c + +/* + * Next software beacon alert register + */ +#define AR5K_AR5212_TIMER2 0x8030 + +/* + * Next ATIM window time register + */ +#define AR5K_AR5212_TIMER3 0x8034 + +/* + * CFP duration register + */ +#define AR5K_AR5212_CFP_DUR 0x8038 + +/* + * Receive filter register + */ +#define AR5K_AR5212_RX_FILTER 0x803c +#define AR5K_AR5212_RX_FILTER_UNICAST 0x00000001 +#define AR5K_AR5212_RX_FILTER_MULTICAST 0x00000002 +#define AR5K_AR5212_RX_FILTER_BROADCAST 0x00000004 +#define AR5K_AR5212_RX_FILTER_CONTROL 0x00000008 +#define AR5K_AR5212_RX_FILTER_BEACON 0x00000010 +#define AR5K_AR5212_RX_FILTER_PROMISC 0x00000020 +#define AR5K_AR5212_RX_FILTER_XR_POLL 0x00000040 +#define AR5K_AR5212_RX_FILTER_PROBE_REQ 0x00000080 + +/* + * Multicast filter register (lower 32 bits) + */ +#define AR5K_AR5212_MCAST_FIL0 0x8040 + +/* + * Multicast filter register (higher 16 bits) + */ +#define AR5K_AR5212_MCAST_FIL1 0x8044 + +/* + * PCU control register + */ +#define AR5K_AR5212_DIAG_SW 0x8048 +#define AR5K_AR5212_DIAG_SW_DIS_WEP_ACK 0x00000001 +#define AR5K_AR5212_DIAG_SW_DIS_ACK 0x00000002 +#define AR5K_AR5212_DIAG_SW_DIS_CTS 0x00000004 +#define AR5K_AR5212_DIAG_SW_DIS_ENC 0x00000008 +#define AR5K_AR5212_DIAG_SW_DIS_DEC 0x00000010 +#define AR5K_AR5212_DIAG_SW_DIS_RX 0x00000020 +#define AR5K_AR5212_DIAG_SW_LOOP_BACK 0x00000040 +#define AR5K_AR5212_DIAG_SW_CORR_FCS 0x00000080 +#define AR5K_AR5212_DIAG_SW_CHAN_INFO 0x00000100 +#define AR5K_AR5212_DIAG_SW_EN_SCRAM_SEED 0x00000200 +#define AR5K_AR5212_DIAG_SW_ECO_ENABLE 0x00000400 +#define AR5K_AR5212_DIAG_SW_SCRAM_SEED_M 0x0001fc00 +#define AR5K_AR5212_DIAG_SW_SCRAM_SEED_S 10 +#define AR5K_AR5212_DIAG_SW_FRAME_NV0 0x00020000 +#define AR5K_AR5212_DIAG_SW_OBSPT_M 0x000c0000 +#define AR5K_AR5212_DIAG_SW_OBSPT_S 18 + +/* + * TSF (clock) register (lower 32 bits) + */ +#define AR5K_AR5212_TSF_L32 0x804c + +/* + * TSF (clock) register (higher 32 bits) + */ +#define AR5K_AR5212_TSF_U32 0x8050 + +/* + * ADDAC test register + */ +#define AR5K_AR5212_ADDAC_TEST 0x8054 + +/* + * Default antenna register + */ +#define AR5K_AR5212_DEFAULT_ANTENNA 0x8058 + +/* + * Last beacon timestamp register + */ +#define AR5K_AR5212_LAST_TSTP 0x8080 + +/* + * NAV register (current) + */ +#define AR5K_AR5212_NAV 0x8084 + +/* + * RTS success register + */ +#define AR5K_AR5212_RTS_OK 0x8088 + +/* + * RTS failure register + */ +#define AR5K_AR5212_RTS_FAIL 0x808c + +/* + * ACK failure register + */ +#define AR5K_AR5212_ACK_FAIL 0x8090 + +/* + * FCS failure register + */ +#define AR5K_AR5212_FCS_FAIL 0x8094 + +/* + * Beacon count register + */ +#define AR5K_AR5212_BEACON_CNT 0x8098 + +/* + * XR (eXtended Range) mode register + */ +#define AR5K_AR5212_XRMODE 0x80c0 +#define AR5K_AR5212_XRMODE_POLL_TYPE_M 0x0000003f +#define AR5K_AR5212_XRMODE_POLL_TYPE_S 0 +#define AR5K_AR5212_XRMODE_POLL_SUBTYPE_M 0x0000003c +#define AR5K_AR5212_XRMODE_POLL_SUBTYPE_S 2 +#define AR5K_AR5212_XRMODE_POLL_WAIT_ALL 0x00000080 +#define AR5K_AR5212_XRMODE_SIFS_DELAY 0x000fff00 +#define AR5K_AR5212_XRMODE_FRAME_HOLD_M 0xfff00000 +#define AR5K_AR5212_XRMODE_FRAME_HOLD_S 20 + +/* + * XR delay register + */ +#define AR5K_AR5212_XRDELAY 0x80c4 +#define AR5K_AR5212_XRDELAY_SLOT_DELAY_M 0x0000ffff +#define AR5K_AR5212_XRDELAY_SLOT_DELAY_S 0 +#define AR5K_AR5212_XRDELAY_CHIRP_DELAY_M 0xffff0000 +#define AR5K_AR5212_XRDELAY_CHIRP_DELAY_S 16 + +/* + * XR timeout register + */ +#define AR5K_AR5212_XRTIMEOUT 0x80c8 +#define AR5K_AR5212_XRTIMEOUT_CHIRP_M 0x0000ffff +#define AR5K_AR5212_XRTIMEOUT_CHIRP_S 0 +#define AR5K_AR5212_XRTIMEOUT_POLL_M 0xffff0000 +#define AR5K_AR5212_XRTIMEOUT_POLL_S 16 + +/* + * XR chirp register + */ +#define AR5K_AR5212_XRCHIRP 0x80cc +#define AR5K_AR5212_XRCHIRP_SEND 0x00000001 +#define AR5K_AR5212_XRCHIRP_GAP 0xffff0000 + +/* + * XR stomp register + */ +#define AR5K_AR5212_XRSTOMP 0x80d0 +#define AR5K_AR5212_XRSTOMP_TX 0x00000001 +#define AR5K_AR5212_XRSTOMP_RX_ABORT 0x00000002 +#define AR5K_AR5212_XRSTOMP_RSSI_THRES 0x0000ff00 + +/* + * First enhanced sleep register + */ +#define AR5K_AR5212_SLEEP0 0x80d4 +#define AR5K_AR5212_SLEEP0_NEXT_DTIM_M 0x0007ffff +#define AR5K_AR5212_SLEEP0_NEXT_DTIM_S 0 +#define AR5K_AR5212_SLEEP0_ASSUME_DTIM 0x00080000 +#define AR5K_AR5212_SLEEP0_ENH_SLEEP_EN 0x00100000 +#define AR5K_AR5212_SLEEP0_CAPTO_M 0xff000000 +#define AR5K_AR5212_SLEEP0_CAPTO_S 24 + +/* + * Second enhanced sleep register + */ +#define AR5K_AR5212_SLEEP1 0x80d8 +#define AR5K_AR5212_SLEEP1_NEXT_TIM_M 0x0007ffff +#define AR5K_AR5212_SLEEP1_NEXT_TIM_S 0 +#define AR5K_AR5212_SLEEP1_BEACON_TO_M 0xff000000 +#define AR5K_AR5212_SLEEP1_BEACON_TO_S 24 + +/* + * Third enhanced sleep register + */ +#define AR5K_AR5212_SLEEP2 0x80dc +#define AR5K_AR5212_SLEEP2_TIM_PER_M 0x0000ffff +#define AR5K_AR5212_SLEEP2_TIM_PER_S 0 +#define AR5K_AR5212_SLEEP2_DTIM_PER_M 0xffff0000 +#define AR5K_AR5212_SLEEP2_DTIM_PER_S 16 + +/* + * BSSID mask registers + */ +#define AR5K_AR5212_BSS_IDM0 0x80e0 +#define AR5K_AR5212_BSS_IDM1 0x80e4 + +/* + * TX power control (TPC) register + */ +#define AR5K_AR5212_TXPC 0x80e8 +#define AR5K_AR5212_TXPC_ACK_M 0x0000003f +#define AR5K_AR5212_TXPC_ACK_S 0 +#define AR5K_AR5212_TXPC_CTS_M 0x00003f00 +#define AR5K_AR5212_TXPC_CTS_S 8 +#define AR5K_AR5212_TXPC_CHIRP_M 0x003f0000 +#define AR5K_AR5212_TXPC_CHIRP_S 22 + +/* + * Profile count registers + */ +#define AR5K_AR5212_PROFCNT_TX 0x80ec +#define AR5K_AR5212_PROFCNT_RX 0x80f0 +#define AR5K_AR5212_PROFCNT_RXCLR 0x80f4 +#define AR5K_AR5212_PROFCNT_CYCLE 0x80f8 + +/* + * TSF parameter register + */ +#define AR5K_AR5212_TSF_PARM 0x8104 +#define AR5K_AR5212_TSF_PARM_INC_M 0x000000ff +#define AR5K_AR5212_TSF_PARM_INC_S 0 + +/* + * PHY error filter register + */ +#define AR5K_AR5212_PHY_ERR_FIL 0x810c +#define AR5K_AR5212_PHY_ERR_FIL_RADAR 0x00000020 +#define AR5K_AR5212_PHY_ERR_FIL_OFDM 0x00020000 +#define AR5K_AR5212_PHY_ERR_FIL_CCK 0x02000000 + +/* + * Rate duration register + */ +#define AR5K_AR5212_RATE_DUR_0 0x8700 +#define AR5K_AR5212_RATE_DUR(_n) (AR5K_AR5212_RATE_DUR_0 + ((_n) << 2)) + +/* + * Key table (WEP) register + */ +#define AR5K_AR5212_KEYTABLE_0 0x8800 +#define AR5K_AR5212_KEYTABLE(n) (AR5K_AR5212_KEYTABLE_0 + ((n) * 32)) +#define AR5K_AR5212_KEYTABLE_TYPE_40 0x00000000 +#define AR5K_AR5212_KEYTABLE_TYPE_104 0x00000001 +#define AR5K_AR5212_KEYTABLE_TYPE_128 0x00000003 +#define AR5K_AR5212_KEYTABLE_TYPE_TKIP 0x00000004 +#define AR5K_AR5212_KEYTABLE_TYPE_AES 0x00000005 +#define AR5K_AR5212_KEYTABLE_TYPE_CCM 0x00000006 +#define AR5K_AR5212_KEYTABLE_TYPE_NULL 0x00000007 +#define AR5K_AR5212_KEYTABLE_ANTENNA 0x00000008 +#define AR5K_AR5212_KEYTABLE_VALID 0x00008000 + +#define AR5K_AR5212_KEYTABLE_SIZE 64 +#define AR5K_AR5212_KEYCACHE_SIZE 8 + +/* + * PHY register + */ +#define AR5K_AR5212_PHY(_n) (0x9800 + ((_n) << 2)) +#define AR5K_AR5212_PHY_SHIFT_2GHZ 0x00004007 +#define AR5K_AR5212_PHY_SHIFT_5GHZ 0x00000007 + +/* + * PHY turbo mode register + */ +#define AR5K_AR5212_PHY_TURBO 0x9804 +#define AR5K_AR5212_PHY_TURBO_MODE 0x00000001 +#define AR5K_AR5212_PHY_TURBO_SHORT 0x00000002 + +/* + * PHY agility command register + */ +#define AR5K_AR5212_PHY_AGC 0x9808 +#define AR5K_AR5212_PHY_AGC_DISABLE 0x08000000 + +/* + * PHY timing register + */ +#define AR5K_AR5212_PHY_TIMING_3 0x9814 +#define AR5K_AR5212_PHY_TIMING_3_DSC_MAN 0xfffe0000 +#define AR5K_AR5212_PHY_TIMING_3_DSC_MAN_S 17 +#define AR5K_AR5212_PHY_TIMING_3_DSC_EXP 0x0001e000 +#define AR5K_AR5212_PHY_TIMING_3_DSC_EXP_S 13 + +/* + * PHY chip revision register + */ +#define AR5K_AR5212_PHY_CHIP_ID 0x9818 + +/* + * PHY activation register + */ +#define AR5K_AR5212_PHY_ACTIVE 0x981c +#define AR5K_AR5212_PHY_ENABLE 0x00000001 +#define AR5K_AR5212_PHY_DISABLE 0x00000002 + +/* + * PHY agility control register + */ +#define AR5K_AR5212_PHY_AGCCTL 0x9860 +#define AR5K_AR5212_PHY_AGCCTL_CAL 0x00000001 +#define AR5K_AR5212_PHY_AGCCTL_NF 0x00000002 + +/* + * PHY noise floor status register + */ +#define AR5K_AR5212_PHY_NF 0x9864 +#define AR5K_AR5212_PHY_NF_M 0x000001ff +#define AR5K_AR5212_PHY_NF_ACTIVE 0x00000100 +#define AR5K_AR5212_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_AR5212_PHY_NF_M) +#define AR5K_AR5212_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_AR5212_PHY_NF_M) + 1) +#define AR5K_AR5212_PHY_NF_SVAL(_n) (((_n) & AR5K_AR5212_PHY_NF_M) | (1 << 9)) + +/* + * PHY sleep registers + */ +#define AR5K_AR5212_PHY_SCR 0x9870 +#define AR5K_AR5212_PHY_SCR_32MHZ 0x0000001f +#define AR5K_AR5212_PHY_SLMT 0x9874 +#define AR5K_AR5212_PHY_SLMT_32MHZ 0x0000007f +#define AR5K_AR5212_PHY_SCAL 0x9878 +#define AR5K_AR5212_PHY_SCAL_32MHZ 0x0000000e + +/* + * PHY PLL control register + */ +#define AR5K_AR5212_PHY_PLL 0x987c +#define AR5K_AR5212_PHY_PLL_40MHZ 0x000000aa +#define AR5K_AR5212_PHY_PLL_44MHZ 0x000000ab +#define AR5K_AR5212_PHY_PLL_AR5111 0x00000000 +#define AR5K_AR5212_PHY_PLL_AR5112 0x00000040 + +/* + * PHY receiver delay register + */ +#define AR5K_AR5212_PHY_RX_DELAY 0x9914 +#define AR5K_AR5212_PHY_RX_DELAY_M 0x00003fff + +/* + * PHY timing IQ control register + */ +#define AR5K_AR5212_PHY_IQ 0x9920 +#define AR5K_AR5212_PHY_IQ_CORR_Q_Q_COFF 0x0000001f +#define AR5K_AR5212_PHY_IQ_CORR_Q_I_COFF 0x000007e0 +#define AR5K_AR5212_PHY_IQ_CORR_Q_I_COFF_S 5 +#define AR5K_AR5212_PHY_IQ_CORR_ENABLE 0x00000800 +#define AR5K_AR5212_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 +#define AR5K_AR5212_PHY_IQ_CAL_NUM_LOG_MAX_S 12 +#define AR5K_AR5212_PHY_IQ_RUN 0x00010000 + +/* + * PHY PAPD probe register + */ +#define AR5K_AR5212_PHY_PAPD_PROBE 0x9930 +#define AR5K_AR5212_PHY_PAPD_PROBE_TXPOWER 0x00007e00 +#define AR5K_AR5212_PHY_PAPD_PROBE_TXPOWER_S 9 +#define AR5K_AR5212_PHY_PAPD_PROBE_TX_NEXT 0x00008000 +#define AR5K_AR5212_PHY_PAPD_PROBE_GAINF 0xfe000000 +#define AR5K_AR5212_PHY_PAPD_PROBE_GAINF_S 25 + +/* + * PHY TX power registers + */ +#define AR5K_AR5212_PHY_TXPOWER_RATE1 0x9934 +#define AR5K_AR5212_PHY_TXPOWER_RATE2 0x9938 +#define AR5K_AR5212_PHY_TXPOWER_RATE_MAX 0x993c +#define AR5K_AR5212_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040 +#define AR5K_AR5212_PHY_TXPOWER_RATE3 0xa234 +#define AR5K_AR5212_PHY_TXPOWER_RATE4 0xa238 + +/* + * PHY frame control register + */ +#define AR5K_AR5212_PHY_FC 0x9944 +#define AR5K_AR5212_PHY_FC_TX_CLIP 0x00000038 +#define AR5K_AR5212_PHY_FC_TX_CLIP_S 3 + +/* + * PHY radar detection enable register + */ +#define AR5K_AR5212_PHY_RADAR 0x9954 +#define AR5K_AR5212_PHY_RADAR_DISABLE 0x00000000 +#define AR5K_AR5212_PHY_RADAR_ENABLE 0x00000001 + +/* + * PHY antenna switch table registers + */ +#define AR5K_AR5212_PHY_ANT_SWITCH_TABLE_0 0x9960 +#define AR5K_AR5212_PHY_ANT_SWITCH_TABLE_1 0x9964 + +/* + * PHY clock sleep registers + */ +#define AR5K_AR5212_PHY_SCLOCK 0x99f0 +#define AR5K_AR5212_PHY_SCLOCK_32MHZ 0x0000000c +#define AR5K_AR5212_PHY_SDELAY 0x99f4 +#define AR5K_AR5212_PHY_SDELAY_32MHZ 0x000000ff +#define AR5K_AR5212_PHY_SPENDING 0x99f8 +#define AR5K_AR5212_PHY_SPENDING_AR5111 0x00000018 +#define AR5K_AR5212_PHY_SPENDING_AR5112 0x00000014 + +/* + * PHY timing IQ calibration result register + */ +#define AR5K_AR5212_PHY_IQRES_CAL_PWR_I 0x9c10 +#define AR5K_AR5212_PHY_IQRES_CAL_PWR_Q 0x9c14 +#define AR5K_AR5212_PHY_IQRES_CAL_CORR 0x9c18 + +/* + * PHY current RSSI register + */ +#define AR5K_AR5212_PHY_CURRENT_RSSI 0x9c1c + +/* + * PHY PCDAC TX power register + */ +#define AR5K_AR5212_PHY_PCDAC_TXPOWER(_n) (0xa180 + ((_n) << 2)) + +/* + * PHY mode register + */ +#define AR5K_AR5212_PHY_MODE 0x0a200 +#define AR5K_AR5212_PHY_MODE_MOD 0x00000001 +#define AR5K_AR5212_PHY_MODE_MOD_OFDM 0 +#define AR5K_AR5212_PHY_MODE_MOD_CCK 1 +#define AR5K_AR5212_PHY_MODE_FREQ 0x00000002 +#define AR5K_AR5212_PHY_MODE_FREQ_5GHZ 0 +#define AR5K_AR5212_PHY_MODE_FREQ_2GHZ 2 +#define AR5K_AR5212_PHY_MODE_MOD_DYN 0x00000004 +#define AR5K_AR5212_PHY_MODE_RAD 0x00000008 +#define AR5K_AR5212_PHY_MODE_RAD_AR5111 0 +#define AR5K_AR5212_PHY_MODE_RAD_AR5112 8 +#define AR5K_AR5212_PHY_MODE_XR 0x00000010 + +/* + * PHY 2GHz gain register + */ +#define AR5K_AR5212_PHY_GAIN_2GHZ 0xa20c +#define AR5K_AR5212_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000 +#define AR5K_AR5212_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18 + +#endif diff --git a/sys/dev/ic/ar5212var.h b/sys/dev/ic/ar5212var.h new file mode 100644 index 00000000000..2bbf18022af --- /dev/null +++ b/sys/dev/ic/ar5212var.h @@ -0,0 +1,915 @@ +/* $OpenBSD: ar5212var.h,v 1.1 2005/02/19 16:58:00 reyk Exp $ */ + +/* + * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Specific definitions for the Atheros AR5001 Wireless LAN chipset + * (AR5212/AR5311). + */ + +#ifndef _AR5K_AR5212_VAR_H +#define _AR5K_AR5212_VAR_H + +#include <dev/ic/ar5xxx.h> + +/* + * Define a "magic" code for the AR5212 (the HAL layer wants it) + */ + +#define AR5K_AR5212_MAGIC 0x0000145b /* 5212 */ +#define AR5K_AR5212_TX_NUM_QUEUES 10 + +#if BYTE_ORDER == BIG_ENDIAN +#define AR5K_AR5212_INIT_CFG ( \ + AR5K_AR5212_CFG_SWTD | AR5K_AR5212_CFG_SWTB | \ + AR5K_AR5212_CFG_SWRD | AR5K_AR5212_CFG_SWRB | \ + AR5K_AR5212_CFG_SWRG \ +) +#else +#define AR5K_AR5212_INIT_CFG 0x00000000 +#endif + +/* + * Internal RX/TX descriptor structures + * (rX: reserved fields possibily used by future versions of the ar5k chipset) + */ + +struct ar5k_ar5212_rx_desc { + /* + * rx_control_0 + */ + u_int32_t reserved:32; + + /* + * rx_control_1 + */ + u_int32_t buf_len:12; + u_int32_t reserved_12:1; + u_int32_t inter_req:1; + u_int32_t reserved_14_31:18; +} __packed; + +struct ar5k_ar5212_rx_status { + /* + * rx_status_0 + */ + u_int32_t data_len:12; + u_int32_t more:1; + u_int32_t decomp_crc_error:1; + u_int32_t reserved_14:1; + u_int32_t receive_rate:5; + u_int32_t receive_sig_strength:8; + u_int32_t receive_antenna:4; + + /* + * rx_status_1 + */ + u_int32_t done:1; + u_int32_t frame_receive_ok:1; + u_int32_t crc_error:1; + u_int32_t decrypt_crc_error:1; + u_int32_t phy_error:1; + u_int32_t mic_error:1; + u_int32_t reserved_6_7:2; + u_int32_t key_index_valid:1; + u_int32_t key_index:7; + u_int32_t receive_timestamp:15; + u_int32_t key_cache_miss:1; +} __packed; + +struct ar5k_ar5212_rx_error { + /* + * rx_error_0 + */ + u_int32_t reserved:32; + + /* + * rx_error_1 + */ + u_int32_t reserved_1_7:8; + u_int32_t phy_error_code:8; + u_int32_t reserved_16_31:16; +} __packed; + +#define AR5K_AR5212_DESC_RX_PHY_ERROR_NONE 0x00 +#define AR5K_AR5212_DESC_RX_PHY_ERROR_TIMING 0x20 +#define AR5K_AR5212_DESC_RX_PHY_ERROR_PARITY 0x40 +#define AR5K_AR5212_DESC_RX_PHY_ERROR_RATE 0x60 +#define AR5K_AR5212_DESC_RX_PHY_ERROR_LENGTH 0x80 +#define AR5K_AR5212_DESC_RX_PHY_ERROR_64QAM 0xa0 +#define AR5K_AR5212_DESC_RX_PHY_ERROR_SERVICE 0xc0 +#define AR5K_AR5212_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 + +struct ar5k_ar5212_tx_desc { + /* + * tx_control_0 + */ + u_int32_t frame_len:12; + u_int32_t reserved_12_15:4; + u_int32_t xmit_power:6; + u_int32_t rts_cts_enable:1; + u_int32_t veol:1; + u_int32_t clear_dest_mask:1; + u_int32_t ant_mode_xmit:4; + u_int32_t inter_req:1; + u_int32_t encrypt_key_valid:1; + u_int32_t cts_enable:1; + + /* + * tx_control_1 + */ + u_int32_t buf_len:12; + u_int32_t more:1; + u_int32_t encrypt_key_index:7; + u_int32_t frame_type:4; + u_int32_t no_ack:1; + u_int32_t comp_proc:2; + u_int32_t comp_iv_len:2; + u_int32_t comp_icv_len:2; + u_int32_t reserved_31:1; + + /* + * tx_control_2 + */ + u_int32_t rts_duration:15; + u_int32_t duration_update_enable:1; + u_int32_t xmit_tries0:4; + u_int32_t xmit_tries1:4; + u_int32_t xmit_tries2:4; + u_int32_t xmit_tries3:4; + + /* + * tx_control_3 + */ + u_int32_t xmit_rate0:5; + u_int32_t xmit_rate1:5; + u_int32_t xmit_rate2:5; + u_int32_t xmit_rate3:5; + u_int32_t rts_cts_rate:5; + u_int32_t reserved_25_31:7; +} __packed; + +#define AR5K_AR5212_DESC_TX_XMIT_RATE_6 0xb +#define AR5K_AR5212_DESC_TX_XMIT_RATE_9 0xf +#define AR5K_AR5212_DESC_TX_XMIT_RATE_12 0xa +#define AR5K_AR5212_DESC_TX_XMIT_RATE_18 0xe +#define AR5K_AR5212_DESC_TX_XMIT_RATE_24 0x9 +#define AR5K_AR5212_DESC_TX_XMIT_RATE_36 0xd +#define AR5K_AR5212_DESC_TX_XMIT_RATE_48 0x8 +#define AR5K_AR5212_DESC_TX_XMIT_RATE_54 0xc + +#define AR5K_AR5212_DESC_TX_FRAME_TYPE_NORMAL 0x00 +#define AR5K_AR5212_DESC_TX_FRAME_TYPE_ATIM 0x04 +#define AR5K_AR5212_DESC_TX_FRAME_TYPE_PSPOLL 0x08 +#define AR5K_AR5212_DESC_TX_FRAME_TYPE_NO_DELAY 0x0c +#define AR5K_AR5212_DESC_TX_FRAME_TYPE_PIFS 0x10 + +struct ar5k_ar5212_tx_status { + /* + * tx_status_0 + */ + u_int32_t frame_xmit_ok:1; + u_int32_t excessive_retries:1; + u_int32_t fifo_underrun:1; + u_int32_t filtered:1; + u_int32_t rts_fail_count:4; + u_int32_t data_fail_count:4; + u_int32_t virt_coll_count:4; + u_int32_t send_timestamp:16; + + /* + * tx_status_1 + */ + u_int32_t done:1; + u_int32_t seq_num:12; + u_int32_t ack_sig_strength:8; + u_int32_t final_ts_index:2; + u_int32_t comp_success:1; + u_int32_t xmit_antenna:1; + u_int32_t reserved_25_31:7; +} __packed; + +/* + * Public function prototypes + */ +extern ar5k_attach_t ar5k_ar5212_attach; + +/* + * Initial register values which have to be loaded into the + * card at boot time and after each reset. + */ + +struct ar5k_ar5212_ini { + u_int8_t ini_flags; + u_int16_t ini_register; + u_int32_t ini_value; + +#define AR5K_INI_FLAG_511X 0x00 +#define AR5K_INI_FLAG_5111 0x01 +#define AR5K_INI_FLAG_5112 0x02 +#define AR5K_INI_FLAG_BOTH (AR5K_INI_FLAG_5111 | AR5K_INI_FLAG_5112) +}; + +#define AR5K_AR5212_INI { \ + { AR5K_INI_FLAG_BOTH, 0x000c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0034, 0x00000005 }, \ + { AR5K_INI_FLAG_BOTH, 0x0040, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0044, 0x00000008 }, \ + { AR5K_INI_FLAG_BOTH, 0x0048, 0x00000008 }, \ + { AR5K_INI_FLAG_BOTH, 0x004c, 0x00000010 }, \ + { AR5K_INI_FLAG_BOTH, 0x0050, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0054, 0x0000001f }, \ + { AR5K_INI_FLAG_BOTH, 0x0800, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0804, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0808, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x080c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0810, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0814, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0818, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x081c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0820, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x0824, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1230, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1270, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1038, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1078, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x10b8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x10f8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1138, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1178, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x11b8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x11f8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1238, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1278, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x12b8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x12f8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1338, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1378, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x13b8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x13f8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1438, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1478, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x14b8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x14f8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1538, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1578, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x15b8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x15f8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1638, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1678, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x16b8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x16f8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1738, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x1778, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x17b8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x17f8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x103c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x107c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x10bc, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x10fc, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x113c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x117c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x11bc, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x11fc, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x123c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x127c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x12bc, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x12fc, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x133c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x137c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x13bc, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x13fc, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x143c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x147c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8004, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8008, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x800c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8018, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8020, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8024, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8028, 0x00000030 }, \ + { AR5K_INI_FLAG_BOTH, 0x802c, 0x0007ffff }, \ + { AR5K_INI_FLAG_BOTH, 0x8030, 0x01ffffff }, \ + { AR5K_INI_FLAG_BOTH, 0x8034, 0x00000031 }, \ + { AR5K_INI_FLAG_BOTH, 0x8038, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x803c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8048, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8054, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8058, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x805c, 0xffffc7ff }, \ + { AR5K_INI_FLAG_BOTH, 0x8080, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8084, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8088, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x808c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8090, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8094, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8098, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x80c0, 0x2a82301a }, \ + { AR5K_INI_FLAG_BOTH, 0x80c4, 0x05dc01e0 }, \ + { AR5K_INI_FLAG_BOTH, 0x80c8, 0x1f402710 }, \ + { AR5K_INI_FLAG_BOTH, 0x80cc, 0x01f40000 }, \ + { AR5K_INI_FLAG_BOTH, 0x80d0, 0x00001e1c }, \ + { AR5K_INI_FLAG_BOTH, 0x80d4, 0x0002aaaa }, \ + { AR5K_INI_FLAG_BOTH, 0x80d8, 0x02005555 }, \ + { AR5K_INI_FLAG_BOTH, 0x80dc, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x80e0, 0xffffffff }, \ + { AR5K_INI_FLAG_BOTH, 0x80e4, 0x0000ffff }, \ + { AR5K_INI_FLAG_BOTH, 0x80e8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x80ec, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x80f0, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x80f4, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x80f8, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x80fc, 0x00000088 }, \ + { AR5K_INI_FLAG_BOTH, 0x8700, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8704, 0x0000008c }, \ + { AR5K_INI_FLAG_BOTH, 0x8708, 0x000000e4 }, \ + { AR5K_INI_FLAG_BOTH, 0x870c, 0x000002d5 }, \ + { AR5K_INI_FLAG_BOTH, 0x8710, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8714, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8718, 0x000000a0 }, \ + { AR5K_INI_FLAG_BOTH, 0x871c, 0x000001c9 }, \ + { AR5K_INI_FLAG_BOTH, 0x8720, 0x0000002c }, \ + { AR5K_INI_FLAG_BOTH, 0x8724, 0x0000002c }, \ + { AR5K_INI_FLAG_BOTH, 0x8728, 0x00000030 }, \ + { AR5K_INI_FLAG_BOTH, 0x872c, 0x0000003c }, \ + { AR5K_INI_FLAG_BOTH, 0x8730, 0x0000002c }, \ + { AR5K_INI_FLAG_BOTH, 0x8734, 0x0000002c }, \ + { AR5K_INI_FLAG_BOTH, 0x8738, 0x00000030 }, \ + { AR5K_INI_FLAG_BOTH, 0x873c, 0x0000003c }, \ + { AR5K_INI_FLAG_BOTH, 0x8740, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8744, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8748, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x874c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8750, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8754, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8758, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x875c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8760, 0x000000d5 }, \ + { AR5K_INI_FLAG_BOTH, 0x8764, 0x000000df }, \ + { AR5K_INI_FLAG_BOTH, 0x8768, 0x00000102 }, \ + { AR5K_INI_FLAG_BOTH, 0x876c, 0x0000013a }, \ + { AR5K_INI_FLAG_BOTH, 0x8770, 0x00000075 }, \ + { AR5K_INI_FLAG_BOTH, 0x8774, 0x0000007f }, \ + { AR5K_INI_FLAG_BOTH, 0x8778, 0x000000a2 }, \ + { AR5K_INI_FLAG_BOTH, 0x877c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8100, 0x00010002 }, \ + { AR5K_INI_FLAG_BOTH, 0x8104, 0x00000001 }, \ + { AR5K_INI_FLAG_BOTH, 0x8108, 0x000000c0 }, \ + { AR5K_INI_FLAG_BOTH, 0x810c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x8110, 0x00000168 }, \ + { AR5K_INI_FLAG_BOTH, 0x8114, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x87c0, 0x03020100 }, \ + { AR5K_INI_FLAG_BOTH, 0x87c4, 0x07060504 }, \ + { AR5K_INI_FLAG_BOTH, 0x87c8, 0x0b0a0908 }, \ + { AR5K_INI_FLAG_BOTH, 0x87cc, 0x0f0e0d0c }, \ + { AR5K_INI_FLAG_BOTH, 0x87d0, 0x13121110 }, \ + { AR5K_INI_FLAG_BOTH, 0x87d4, 0x17161514 }, \ + { AR5K_INI_FLAG_BOTH, 0x87d8, 0x1b1a1918 }, \ + { AR5K_INI_FLAG_BOTH, 0x87dc, 0x1f1e1d1c }, \ + { AR5K_INI_FLAG_BOTH, 0x87e0, 0x03020100 }, \ + { AR5K_INI_FLAG_BOTH, 0x87e4, 0x07060504 }, \ + { AR5K_INI_FLAG_BOTH, 0x87e8, 0x0b0a0908 }, \ + { AR5K_INI_FLAG_BOTH, 0x87ec, 0x0f0e0d0c }, \ + { AR5K_INI_FLAG_BOTH, 0x87f0, 0x13121110 }, \ + { AR5K_INI_FLAG_BOTH, 0x87f4, 0x17161514 }, \ + { AR5K_INI_FLAG_BOTH, 0x87f8, 0x1b1a1918 }, \ + { AR5K_INI_FLAG_BOTH, 0x87fc, 0x1f1e1d1c }, \ + /* PHY registers */ \ + { AR5K_INI_FLAG_BOTH, 0x9808, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x980c, 0xad848e19 }, \ + { AR5K_INI_FLAG_BOTH, 0x9810, 0x7d28e000 }, \ + { AR5K_INI_FLAG_BOTH, 0x9814, 0x9c0a9f6b }, \ + { AR5K_INI_FLAG_BOTH, 0x981c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x982c, 0x00022ffe }, \ + { AR5K_INI_FLAG_BOTH, 0x983c, 0x00020100 }, \ + { AR5K_INI_FLAG_BOTH, 0x9840, 0x206a017a }, \ + { AR5K_INI_FLAG_BOTH, 0x984c, 0x1284613c }, \ + { AR5K_INI_FLAG_BOTH, 0x9854, 0x00000859 }, \ + { AR5K_INI_FLAG_BOTH, 0x9900, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x9904, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x9908, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x990c, 0x00800000 }, \ + { AR5K_INI_FLAG_BOTH, 0x9910, 0x00000001 }, \ + { AR5K_INI_FLAG_BOTH, 0x991c, 0x00000c80 }, \ + { AR5K_INI_FLAG_BOTH, 0x9920, 0x05100000 }, \ + { AR5K_INI_FLAG_BOTH, 0x9928, 0x00000001 }, \ + { AR5K_INI_FLAG_BOTH, 0x992c, 0x00000004 }, \ + { AR5K_INI_FLAG_BOTH, 0x9934, 0x1e1f2022 }, \ + { AR5K_INI_FLAG_BOTH, 0x9938, 0x0a0b0c0d }, \ + { AR5K_INI_FLAG_BOTH, 0x993c, 0x0000003f }, \ + { AR5K_INI_FLAG_BOTH, 0x9940, 0x00000004 }, \ + { AR5K_INI_FLAG_BOTH, 0x9948, 0x9280b212 }, \ + { AR5K_INI_FLAG_BOTH, 0x9954, 0x5d50e188 }, \ + { AR5K_INI_FLAG_BOTH, 0x9958, 0x000000ff }, \ + { AR5K_INI_FLAG_BOTH, 0x995c, 0x004b6a8e }, \ + { AR5K_INI_FLAG_BOTH, 0x9968, 0x000003ce }, \ + { AR5K_INI_FLAG_BOTH, 0x9970, 0x192fb515 }, \ + { AR5K_INI_FLAG_BOTH, 0x9974, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x9978, 0x00000001 }, \ + { AR5K_INI_FLAG_BOTH, 0x997c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0xa184, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa188, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa18c, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa190, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa194, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa198, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa19c, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1a0, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1a4, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1a8, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1ac, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1b0, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1b4, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1b8, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1bc, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1c0, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1c4, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1c8, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1cc, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1d0, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1d4, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1d8, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1dc, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1e0, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1e4, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1e8, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1ec, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1f0, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1f4, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1f8, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa1fc, 0x10ff10ff }, \ + { AR5K_INI_FLAG_BOTH, 0xa210, 0x00806333 }, \ + { AR5K_INI_FLAG_BOTH, 0xa214, 0x00106c10 }, \ + { AR5K_INI_FLAG_BOTH, 0xa218, 0x009c4060 }, \ + { AR5K_INI_FLAG_BOTH, 0xa21c, 0x1883800a }, \ + { AR5K_INI_FLAG_BOTH, 0xa220, 0x018830c6 }, \ + { AR5K_INI_FLAG_BOTH, 0xa224, 0x00000400 }, \ + { AR5K_INI_FLAG_BOTH, 0xa228, 0x000001b5 }, \ + { AR5K_INI_FLAG_BOTH, 0xa22c, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0xa234, 0x20202020 }, \ + { AR5K_INI_FLAG_BOTH, 0xa238, 0x20202020 }, \ + { AR5K_INI_FLAG_BOTH, 0xa23c, 0x13c889af }, \ + { AR5K_INI_FLAG_BOTH, 0xa240, 0x38490a20 }, \ + { AR5K_INI_FLAG_BOTH, 0xa244, 0x00007bb6 }, \ + { AR5K_INI_FLAG_BOTH, 0xa248, 0x0fff3ffc }, \ + { AR5K_INI_FLAG_BOTH, 0x9b00, 0x00000000 }, \ + { AR5K_INI_FLAG_BOTH, 0x9b28, 0x0000000c }, \ + { AR5K_INI_FLAG_BOTH, 0x9b38, 0x00000012 }, \ + { AR5K_INI_FLAG_BOTH, 0x9b64, 0x00000021 }, \ + { AR5K_INI_FLAG_BOTH, 0x9b8c, 0x0000002d }, \ + { AR5K_INI_FLAG_BOTH, 0x9b9c, 0x00000033 }, \ + /* AR5111 specific */ \ + { AR5K_INI_FLAG_5111, 0x9930, 0x00004883 }, \ + { AR5K_INI_FLAG_5111, 0xa204, 0x00000000 }, \ + { AR5K_INI_FLAG_5111, 0xa208, 0xd03e6788 }, \ + { AR5K_INI_FLAG_5111, 0x9b04, 0x00000020 }, \ + { AR5K_INI_FLAG_5111, 0x9b08, 0x00000010 }, \ + { AR5K_INI_FLAG_5111, 0x9b0c, 0x00000030 }, \ + { AR5K_INI_FLAG_5111, 0x9b10, 0x00000008 }, \ + { AR5K_INI_FLAG_5111, 0x9b14, 0x00000028 }, \ + { AR5K_INI_FLAG_5111, 0x9b18, 0x00000004 }, \ + { AR5K_INI_FLAG_5111, 0x9b1c, 0x00000024 }, \ + { AR5K_INI_FLAG_5111, 0x9b20, 0x00000014 }, \ + { AR5K_INI_FLAG_5111, 0x9b24, 0x00000034 }, \ + { AR5K_INI_FLAG_5111, 0x9b2c, 0x0000002c }, \ + { AR5K_INI_FLAG_5111, 0x9b30, 0x00000002 }, \ + { AR5K_INI_FLAG_5111, 0x9b34, 0x00000022 }, \ + { AR5K_INI_FLAG_5111, 0x9b3c, 0x00000032 }, \ + { AR5K_INI_FLAG_5111, 0x9b40, 0x0000000a }, \ + { AR5K_INI_FLAG_5111, 0x9b44, 0x0000002a }, \ + { AR5K_INI_FLAG_5111, 0x9b48, 0x00000006 }, \ + { AR5K_INI_FLAG_5111, 0x9b4c, 0x00000026 }, \ + { AR5K_INI_FLAG_5111, 0x9b50, 0x00000016 }, \ + { AR5K_INI_FLAG_5111, 0x9b54, 0x00000036 }, \ + { AR5K_INI_FLAG_5111, 0x9b58, 0x0000000e }, \ + { AR5K_INI_FLAG_5111, 0x9b5c, 0x0000002e }, \ + { AR5K_INI_FLAG_5111, 0x9b60, 0x00000001 }, \ + { AR5K_INI_FLAG_5111, 0x9b68, 0x00000011 }, \ + { AR5K_INI_FLAG_5111, 0x9b6c, 0x00000031 }, \ + { AR5K_INI_FLAG_5111, 0x9b70, 0x00000009 }, \ + { AR5K_INI_FLAG_5111, 0x9b74, 0x00000029 }, \ + { AR5K_INI_FLAG_5111, 0x9b78, 0x00000005 }, \ + { AR5K_INI_FLAG_5111, 0x9b7c, 0x00000025 }, \ + { AR5K_INI_FLAG_5111, 0x9b80, 0x00000015 }, \ + { AR5K_INI_FLAG_5111, 0x9b84, 0x00000035 }, \ + { AR5K_INI_FLAG_5111, 0x9b88, 0x0000000d }, \ + { AR5K_INI_FLAG_5111, 0x9b90, 0x00000003 }, \ + { AR5K_INI_FLAG_5111, 0x9b94, 0x00000023 }, \ + { AR5K_INI_FLAG_5111, 0x9b98, 0x00000013 }, \ + { AR5K_INI_FLAG_5111, 0x9ba0, 0x0000000b }, \ + { AR5K_INI_FLAG_5111, 0x9ba4, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9ba8, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bac, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bb0, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bb4, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bb8, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bbc, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bc0, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bc4, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bc8, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bcc, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bd0, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bd4, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bd8, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bdc, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9be0, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9be4, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9be8, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bec, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bf0, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bf4, 0x0000002b }, \ + { AR5K_INI_FLAG_5111, 0x9bf8, 0x00000002 }, \ + { AR5K_INI_FLAG_5111, 0x9bfc, 0x00000016 }, \ + /* AR5112 specific */ \ + { AR5K_INI_FLAG_5112, 0x9930, 0x00004882 }, \ + { AR5K_INI_FLAG_5112, 0x9b04, 0x00000001 }, \ + { AR5K_INI_FLAG_5112, 0x9b08, 0x00000002 }, \ + { AR5K_INI_FLAG_5112, 0x9b0c, 0x00000003 }, \ + { AR5K_INI_FLAG_5112, 0x9b10, 0x00000004 }, \ + { AR5K_INI_FLAG_5112, 0x9b14, 0x00000005 }, \ + { AR5K_INI_FLAG_5112, 0x9b18, 0x00000008 }, \ + { AR5K_INI_FLAG_5112, 0x9b1c, 0x00000009 }, \ + { AR5K_INI_FLAG_5112, 0x9b20, 0x0000000a }, \ + { AR5K_INI_FLAG_5112, 0x9b24, 0x0000000b }, \ + { AR5K_INI_FLAG_5112, 0x9b2c, 0x0000000d }, \ + { AR5K_INI_FLAG_5112, 0x9b30, 0x00000010 }, \ + { AR5K_INI_FLAG_5112, 0x9b34, 0x00000011 }, \ + { AR5K_INI_FLAG_5112, 0x9b3c, 0x00000013 }, \ + { AR5K_INI_FLAG_5112, 0x9b40, 0x00000014 }, \ + { AR5K_INI_FLAG_5112, 0x9b44, 0x00000015 }, \ + { AR5K_INI_FLAG_5112, 0x9b48, 0x00000018 }, \ + { AR5K_INI_FLAG_5112, 0x9b4c, 0x00000019 }, \ + { AR5K_INI_FLAG_5112, 0x9b50, 0x0000001a }, \ + { AR5K_INI_FLAG_5112, 0x9b54, 0x0000001b }, \ + { AR5K_INI_FLAG_5112, 0x9b58, 0x0000001c }, \ + { AR5K_INI_FLAG_5112, 0x9b5c, 0x0000001d }, \ + { AR5K_INI_FLAG_5112, 0x9b60, 0x00000020 }, \ + { AR5K_INI_FLAG_5112, 0x9b68, 0x00000022 }, \ + { AR5K_INI_FLAG_5112, 0x9b6c, 0x00000023 }, \ + { AR5K_INI_FLAG_5112, 0x9b70, 0x00000024 }, \ + { AR5K_INI_FLAG_5112, 0x9b74, 0x00000025 }, \ + { AR5K_INI_FLAG_5112, 0x9b78, 0x00000028 }, \ + { AR5K_INI_FLAG_5112, 0x9b7c, 0x00000029 }, \ + { AR5K_INI_FLAG_5112, 0x9b80, 0x0000002a }, \ + { AR5K_INI_FLAG_5112, 0x9b84, 0x0000002b }, \ + { AR5K_INI_FLAG_5112, 0x9b88, 0x0000002c }, \ + { AR5K_INI_FLAG_5112, 0x9b90, 0x00000030 }, \ + { AR5K_INI_FLAG_5112, 0x9b94, 0x00000031 }, \ + { AR5K_INI_FLAG_5112, 0x9b98, 0x00000032 }, \ + { AR5K_INI_FLAG_5112, 0x9ba0, 0x00000034 }, \ + { AR5K_INI_FLAG_5112, 0x9ba4, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9ba8, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bac, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bb0, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bb4, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bb8, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bbc, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bc0, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bc4, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bc8, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bcc, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bd0, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bd4, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bd8, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bdc, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9be0, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9be4, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9be8, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bec, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bf0, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bf4, 0x00000035 }, \ + { AR5K_INI_FLAG_5112, 0x9bf8, 0x00000010 }, \ + { AR5K_INI_FLAG_5112, 0x9bfc, 0x0000001a }, \ +} + +struct ar5k_ar5212_ini_mode { + u_int16_t mode_register; + u_int8_t mode_flags; + u_int32_t mode_value[2][5]; + +#define AR5K_INI_PHY_5111 0 +#define AR5K_INI_PHY_5112 1 +#define AR5K_INI_PHY_511X 1 +}; + +#define AR5K_AR5212_INI_MODE { \ + { 0x0030, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } \ + } }, \ + { 0x1040, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x1044, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x1048, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x104c, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x1050, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x1054, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x1058, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x105c, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x1060, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x1064, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } \ + } }, \ + { 0x1030, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } \ + } }, \ + { 0x1070, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } \ + } }, \ + { 0x10b0, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } \ + } }, \ + { 0x10f0, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } \ + } }, \ + { 0x8014, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } \ + } }, \ + { 0x9804, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } \ + } }, \ + { 0x9820, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } \ + } }, \ + { 0x9834, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } \ + } }, \ + { 0x9838, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } \ + } }, \ + { 0x9844, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x1372161c, 0x13721c25, 0x13721728, 0x137216a2, 0x13721c25 } \ + } }, \ + { 0x9850, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } \ + } }, \ + { 0x9860, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } \ + } }, \ + { 0x9864, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } \ + } }, \ + { 0x9868, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } \ + } }, \ + { 0x9918, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } \ + } }, \ + { 0x9924, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } \ + } }, \ + { 0xa180, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x10ff14ff, 0x10ff14ff, 0x10ff10ff, 0x10ff19ff, 0x10ff19ff } \ + } }, \ + { 0xa230, AR5K_INI_FLAG_511X, { \ + { 0, }, \ + { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } \ + } }, \ + { 0x801c, AR5K_INI_FLAG_BOTH, { \ + { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x128d8fab, 0x09880fcf }, \ + { 0x128d93a7, 0x098813cf, 0x04e01395, 0x128d93ab, 0x098813cf } \ + } }, \ + { 0x9824, AR5K_INI_FLAG_BOTH, { \ + { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e }, \ + { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } \ + } }, \ + { 0x9828, AR5K_INI_FLAG_BOTH, { \ + { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 }, \ + { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } \ + } }, \ + { 0x9848, AR5K_INI_FLAG_BOTH, { \ + { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 }, \ + { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } \ + } }, \ + { 0x9858, AR5K_INI_FLAG_BOTH, { \ + { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e }, \ + { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } \ + } }, \ + { 0x985c, AR5K_INI_FLAG_BOTH, { \ + { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e }, \ + { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } \ + } }, \ + { 0x986c, AR5K_INI_FLAG_BOTH, { \ + { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 }, \ + { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } \ + } }, \ + { 0x9914, AR5K_INI_FLAG_BOTH, { \ + { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 }, \ + { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } \ + } }, \ + { 0x9944, AR5K_INI_FLAG_BOTH, { \ + { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 }, \ + { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } \ + } }, \ + { 0xa204, AR5K_INI_FLAG_5112, { \ + { 0, }, \ + { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } \ + } }, \ + { 0xa208, AR5K_INI_FLAG_5112, { \ + { 0, }, \ + { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } \ + } }, \ + { 0xa20c, AR5K_INI_FLAG_BOTH, { \ + { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a }, \ + { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } \ + } }, \ +} + +struct ar5k_ar5212_ini_rfgain { + u_int16_t rfg_register; + u_int32_t rfg_value[2][2]; + +#define AR5K_INI_RFGAIN_5GHZ 0 +#define AR5K_INI_RFGAIN_2GHZ 1 +}; + +#define AR5K_AR5212_INI_RFGAIN { \ + { 0x9a00, { \ + { 0x000001a9, 0x00000000 }, { 0x00000007, 0x00000007 } } }, \ + { 0x9a04, { \ + { 0x000001e9, 0x00000040 }, { 0x00000047, 0x00000047 } } }, \ + { 0x9a08, { \ + { 0x00000029, 0x00000080 }, { 0x00000087, 0x00000087 } } }, \ + { 0x9a0c, { \ + { 0x00000069, 0x00000150 }, { 0x000001a0, 0x000001a0 } } }, \ + { 0x9a10, { \ + { 0x00000199, 0x00000190 }, { 0x000001e0, 0x000001e0 } } }, \ + { 0x9a14, { \ + { 0x000001d9, 0x000001d0 }, { 0x00000020, 0x00000020 } } }, \ + { 0x9a18, { \ + { 0x00000019, 0x00000010 }, { 0x00000060, 0x00000060 } } }, \ + { 0x9a1c, { \ + { 0x00000059, 0x00000044 }, { 0x000001a1, 0x000001a1 } } }, \ + { 0x9a20, { \ + { 0x00000099, 0x00000084 }, { 0x000001e1, 0x000001e1 } } }, \ + { 0x9a24, { \ + { 0x000001a5, 0x00000148 }, { 0x00000021, 0x00000021 } } }, \ + { 0x9a28, { \ + { 0x000001e5, 0x00000188 }, { 0x00000061, 0x00000061 } } }, \ + { 0x9a2c, { \ + { 0x00000025, 0x000001c8 }, { 0x00000162, 0x00000162 } } }, \ + { 0x9a30, { \ + { 0x000001c8, 0x00000014 }, { 0x000001a2, 0x000001a2 } } }, \ + { 0x9a34, { \ + { 0x00000008, 0x00000042 }, { 0x000001e2, 0x000001e2 } } }, \ + { 0x9a38, { \ + { 0x00000048, 0x00000082 }, { 0x00000022, 0x00000022 } } }, \ + { 0x9a3c, { \ + { 0x00000088, 0x00000178 }, { 0x00000062, 0x00000062 } } }, \ + { 0x9a40, { \ + { 0x00000198, 0x000001b8 }, { 0x00000163, 0x00000163 } } }, \ + { 0x9a44, { \ + { 0x000001d8, 0x000001f8 }, { 0x000001a3, 0x000001a3 } } }, \ + { 0x9a48, { \ + { 0x00000018, 0x00000012 }, { 0x000001e3, 0x000001e3 } } }, \ + { 0x9a4c, { \ + { 0x00000058, 0x00000052 }, { 0x00000023, 0x00000023 } } }, \ + { 0x9a50, { \ + { 0x00000098, 0x00000092 }, { 0x00000063, 0x00000063 } } }, \ + { 0x9a54, { \ + { 0x000001a4, 0x0000017c }, { 0x00000184, 0x00000184 } } }, \ + { 0x9a58, { \ + { 0x000001e4, 0x000001bc }, { 0x000001c4, 0x000001c4 } } }, \ + { 0x9a5c, { \ + { 0x00000024, 0x000001fc }, { 0x00000004, 0x00000004 } } }, \ + { 0x9a60, { \ + { 0x00000064, 0x0000000a }, { 0x000001ea, 0x0000000b } } }, \ + { 0x9a64, { \ + { 0x000000a4, 0x0000004a }, { 0x0000002a, 0x0000004b } } }, \ + { 0x9a68, { \ + { 0x000000e4, 0x0000008a }, { 0x0000006a, 0x0000008b } } }, \ + { 0x9a6c, { \ + { 0x0000010a, 0x0000015a }, { 0x000000aa, 0x000001ac } } }, \ + { 0x9a70, { \ + { 0x0000014a, 0x0000019a }, { 0x000001ab, 0x000001ec } } }, \ + { 0x9a74, { \ + { 0x0000018a, 0x000001da }, { 0x000001eb, 0x0000002c } } }, \ + { 0x9a78, { \ + { 0x000001ca, 0x0000000e }, { 0x0000002b, 0x00000012 } } }, \ + { 0x9a7c, { \ + { 0x0000000a, 0x0000004e }, { 0x0000006b, 0x00000052 } } }, \ + { 0x9a80, { \ + { 0x0000004a, 0x0000008e }, { 0x000000ab, 0x00000092 } } }, \ + { 0x9a84, { \ + { 0x0000008a, 0x0000015e }, { 0x000001ac, 0x00000193 } } }, \ + { 0x9a88, { \ + { 0x000001ba, 0x0000019e }, { 0x000001ec, 0x000001d3 } } }, \ + { 0x9a8c, { \ + { 0x000001fa, 0x000001de }, { 0x0000002c, 0x00000013 } } }, \ + { 0x9a90, { \ + { 0x0000003a, 0x00000009 }, { 0x0000003a, 0x00000053 } } }, \ + { 0x9a94, { \ + { 0x0000007a, 0x00000049 }, { 0x0000007a, 0x00000093 } } }, \ + { 0x9a98, { \ + { 0x00000186, 0x00000089 }, { 0x000000ba, 0x00000194 } } }, \ + { 0x9a9c, { \ + { 0x000001c6, 0x00000179 }, { 0x000001bb, 0x000001d4 } } }, \ + { 0x9aa0, { \ + { 0x00000006, 0x000001b9 }, { 0x000001fb, 0x00000014 } } }, \ + { 0x9aa4, { \ + { 0x00000046, 0x000001f9 }, { 0x0000003b, 0x0000003a } } }, \ + { 0x9aa8, { \ + { 0x00000086, 0x00000039 }, { 0x0000007b, 0x0000007a } } }, \ + { 0x9aac, { \ + { 0x000000c6, 0x00000079 }, { 0x000000bb, 0x000000ba } } }, \ + { 0x9ab0, { \ + { 0x000000c6, 0x000000b9 }, { 0x000001bc, 0x000001bb } } }, \ + { 0x9ab4, { \ + { 0x000000c6, 0x000001bd }, { 0x000001fc, 0x000001fb } } }, \ + { 0x9ab8, { \ + { 0x000000c6, 0x000001fd }, { 0x0000003c, 0x0000003b } } }, \ + { 0x9abc, { \ + { 0x000000c6, 0x0000003d }, { 0x0000007c, 0x0000007b } } }, \ + { 0x9ac0, { \ + { 0x000000c6, 0x0000007d }, { 0x000000bc, 0x000000bb } } }, \ + { 0x9ac4, { \ + { 0x000000c6, 0x000000bd }, { 0x000000fc, 0x000001bc } } }, \ + { 0x9ac8, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000001fc } } }, \ + { 0x9acc, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x0000003c } } }, \ + { 0x9ad0, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x0000007c } } }, \ + { 0x9ad4, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000bc } } }, \ + { 0x9ad8, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ + { 0x9adc, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ + { 0x9ae0, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ + { 0x9ae4, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ + { 0x9ae8, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ + { 0x9aec, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ + { 0x9af0, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ + { 0x9af4, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ + { 0x9af8, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ + { 0x9afc, { \ + { 0x000000c6, 0x000000fd }, { 0x000000fc, 0x000000fc } } }, \ +} + +#endif /* _AR5K_AR5212_VAR_H */ diff --git a/sys/dev/ic/ar5xxx.c b/sys/dev/ic/ar5xxx.c index 03f4779e7e3..bb52d096c12 100644 --- a/sys/dev/ic/ar5xxx.c +++ b/sys/dev/ic/ar5xxx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5xxx.c,v 1.12 2005/02/17 23:52:05 reyk Exp $ */ +/* $OpenBSD: ar5xxx.c,v 1.13 2005/02/19 16:58:00 reyk Exp $ */ /* * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> @@ -28,8 +28,8 @@ extern ar5k_attach_t ar5k_ar5210_attach; #ifdef notyet extern ar5k_attach_t ar5k_ar5211_attach; -extern ar5k_attach_t ar5k_ar5212_attach; #endif +extern ar5k_attach_t ar5k_ar5212_attach; static const struct ieee80211_regchannel ar5k_5ghz_channels[] = IEEE80211_CHANNELS_5GHZ; @@ -63,6 +63,7 @@ static const struct { ar5k_ar5211_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_LEGACY, ar5k_ar5211_attach }, +#endif { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_DEFAULT, @@ -74,9 +75,7 @@ static const struct { { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRDAG675, ar5k_ar5212_attach }, { PCI_VENDOR_3COM2, PCI_PRODUCT_3COM2_3CRPAG175, - ar5k_ar5212_attach }, -#endif - + ar5k_ar5212_attach } }; int ar5k_eeprom_read_ants(struct ath_hal *, u_int32_t *, u_int); @@ -103,6 +102,14 @@ static const struct ar5k_ini_rf ar5112_rf[] = AR5K_AR5112_INI_RF; /* + * XXX Overwrite the country code (use "00" for debug) + * XXX as long as ieee80211_regdomain is not finished + */ +#ifndef COUNTRYCODE +#define COUNTRYCODE "us" +#endif + +/* * Perform a lookup if the device is supported by the HAL */ const char * |