diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2005-02-25 22:25:31 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2005-02-25 22:25:31 +0000 |
commit | 7a5ae57cf7496a38699cd390f874fc3359242511 (patch) | |
tree | 620ba16fed20c23692826978981c99dcb2171f35 | |
parent | eaf739340cc437965c78359443b2c66b50cc3f23 (diff) |
add support for the atheros ar5211 802.11A/B/g wireless chipset.
ok deraadt@
-rw-r--r-- | sys/conf/files | 4 | ||||
-rw-r--r-- | sys/dev/ic/ar5211.c | 2488 | ||||
-rw-r--r-- | sys/dev/ic/ar5211reg.h | 1033 | ||||
-rw-r--r-- | sys/dev/ic/ar5211var.h | 396 | ||||
-rw-r--r-- | sys/dev/ic/ar5212.c | 9 | ||||
-rw-r--r-- | sys/dev/ic/ar5212var.h | 147 | ||||
-rw-r--r-- | sys/dev/ic/ar5xxx.c | 39 | ||||
-rw-r--r-- | sys/dev/ic/ar5xxx.h | 148 |
8 files changed, 4104 insertions, 160 deletions
diff --git a/sys/conf/files b/sys/conf/files index e80bdd4da1c..925bd2f43a7 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.328 2005/02/19 16:58:00 reyk Exp $ +# $OpenBSD: files,v 1.329 2005/02/25 22:25:30 reyk Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -330,7 +330,7 @@ file dev/ic/nslm7x.c lm define ar5xxx file dev/ic/ar5xxx.c ar5xxx file dev/ic/ar5210.c ar5xxx -#file dev/ic/ar5211.c ar5xxx +file dev/ic/ar5211.c ar5xxx file dev/ic/ar5212.c ar5xxx # Atheros AR5k (802.11/a/b/g) driver diff --git a/sys/dev/ic/ar5211.c b/sys/dev/ic/ar5211.c new file mode 100644 index 00000000000..0adaf5b861b --- /dev/null +++ b/sys/dev/ic/ar5211.c @@ -0,0 +1,2488 @@ +/* $OpenBSD: ar5211.c,v 1.1 2005/02/25 22:25:30 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 + * (AR5211 + AR5111). + */ + +#include <dev/ic/ar5xxx.h> +#include <dev/ic/ar5211reg.h> +#include <dev/ic/ar5211var.h> + +HAL_BOOL ar5k_ar5211_nic_reset(struct ath_hal *, u_int32_t); +HAL_BOOL ar5k_ar5211_nic_wakeup(struct ath_hal *, u_int16_t); +u_int16_t ar5k_ar5211_radio_revision(struct ath_hal *, HAL_CHIP); +const void ar5k_ar5211_fill(struct ath_hal *); + +/* + * Initial register setting for the AR5211 + */ +static const struct ar5k_ini ar5211_ini[] = + AR5K_AR5211_INI; +static const struct ar5k_ar5211_ini_mode ar5211_mode[] = + AR5K_AR5211_INI_MODE; + +AR5K_HAL_FUNCTIONS(extern, ar5k_ar5211,); + +const void +ar5k_ar5211_fill(hal) + struct ath_hal *hal; +{ + hal->ah_magic = AR5K_AR5211_MAGIC; + + /* + * Init/Exit functions + */ + AR5K_HAL_FUNCTION(hal, ar5211, getRateTable); + AR5K_HAL_FUNCTION(hal, ar5211, detach); + + /* + * Reset functions + */ + AR5K_HAL_FUNCTION(hal, ar5211, reset); + AR5K_HAL_FUNCTION(hal, ar5211, setPCUConfig); + AR5K_HAL_FUNCTION(hal, ar5211, perCalibration); + + /* + * TX functions + */ + AR5K_HAL_FUNCTION(hal, ar5211, updateTxTrigLevel); + AR5K_HAL_FUNCTION(hal, ar5211, setupTxQueue); + AR5K_HAL_FUNCTION(hal, ar5211, setTxQueueProps); + AR5K_HAL_FUNCTION(hal, ar5211, releaseTxQueue); + AR5K_HAL_FUNCTION(hal, ar5211, resetTxQueue); + AR5K_HAL_FUNCTION(hal, ar5211, getTxDP); + AR5K_HAL_FUNCTION(hal, ar5211, setTxDP); + AR5K_HAL_FUNCTION(hal, ar5211, startTxDma); + AR5K_HAL_FUNCTION(hal, ar5211, stopTxDma); + AR5K_HAL_FUNCTION(hal, ar5211, setupTxDesc); + AR5K_HAL_FUNCTION(hal, ar5211, setupXTxDesc); + AR5K_HAL_FUNCTION(hal, ar5211, fillTxDesc); + AR5K_HAL_FUNCTION(hal, ar5211, procTxDesc); + AR5K_HAL_FUNCTION(hal, ar5211, hasVEOL); + + /* + * RX functions + */ + AR5K_HAL_FUNCTION(hal, ar5211, getRxDP); + AR5K_HAL_FUNCTION(hal, ar5211, setRxDP); + AR5K_HAL_FUNCTION(hal, ar5211, enableReceive); + AR5K_HAL_FUNCTION(hal, ar5211, stopDmaReceive); + AR5K_HAL_FUNCTION(hal, ar5211, startPcuReceive); + AR5K_HAL_FUNCTION(hal, ar5211, stopPcuReceive); + AR5K_HAL_FUNCTION(hal, ar5211, setMulticastFilter); + AR5K_HAL_FUNCTION(hal, ar5211, setMulticastFilterIndex); + AR5K_HAL_FUNCTION(hal, ar5211, clrMulticastFilterIndex); + AR5K_HAL_FUNCTION(hal, ar5211, getRxFilter); + AR5K_HAL_FUNCTION(hal, ar5211, setRxFilter); + AR5K_HAL_FUNCTION(hal, ar5211, setupRxDesc); + AR5K_HAL_FUNCTION(hal, ar5211, procRxDesc); + AR5K_HAL_FUNCTION(hal, ar5211, rxMonitor); + + /* + * Misc functions + */ + AR5K_HAL_FUNCTION(hal, ar5211, dumpState); + AR5K_HAL_FUNCTION(hal, ar5211, getDiagState); + AR5K_HAL_FUNCTION(hal, ar5211, getMacAddress); + AR5K_HAL_FUNCTION(hal, ar5211, setMacAddress); + AR5K_HAL_FUNCTION(hal, ar5211, setRegulatoryDomain); + AR5K_HAL_FUNCTION(hal, ar5211, setLedState); + AR5K_HAL_FUNCTION(hal, ar5211, writeAssocid); + AR5K_HAL_FUNCTION(hal, ar5211, gpioCfgInput); + AR5K_HAL_FUNCTION(hal, ar5211, gpioCfgOutput); + AR5K_HAL_FUNCTION(hal, ar5211, gpioGet); + AR5K_HAL_FUNCTION(hal, ar5211, gpioSet); + AR5K_HAL_FUNCTION(hal, ar5211, gpioSetIntr); + AR5K_HAL_FUNCTION(hal, ar5211, getTsf32); + AR5K_HAL_FUNCTION(hal, ar5211, getTsf64); + AR5K_HAL_FUNCTION(hal, ar5211, resetTsf); + AR5K_HAL_FUNCTION(hal, ar5211, getRegDomain); + AR5K_HAL_FUNCTION(hal, ar5211, detectCardPresent); + AR5K_HAL_FUNCTION(hal, ar5211, updateMibCounters); + AR5K_HAL_FUNCTION(hal, ar5211, getRfGain); + AR5K_HAL_FUNCTION(hal, ar5211, setSlotTime); + AR5K_HAL_FUNCTION(hal, ar5211, getSlotTime); + AR5K_HAL_FUNCTION(hal, ar5211, setAckTimeout); + AR5K_HAL_FUNCTION(hal, ar5211, getAckTimeout); + AR5K_HAL_FUNCTION(hal, ar5211, setCTSTimeout); + AR5K_HAL_FUNCTION(hal, ar5211, getCTSTimeout); + + /* + * Key table (WEP) functions + */ + AR5K_HAL_FUNCTION(hal, ar5211, isHwCipherSupported); + AR5K_HAL_FUNCTION(hal, ar5211, getKeyCacheSize); + AR5K_HAL_FUNCTION(hal, ar5211, resetKeyCacheEntry); + AR5K_HAL_FUNCTION(hal, ar5211, isKeyCacheEntryValid); + AR5K_HAL_FUNCTION(hal, ar5211, setKeyCacheEntry); + AR5K_HAL_FUNCTION(hal, ar5211, setKeyCacheEntryMac); + + /* + * Power management functions + */ + AR5K_HAL_FUNCTION(hal, ar5211, setPowerMode); + AR5K_HAL_FUNCTION(hal, ar5211, getPowerMode); + AR5K_HAL_FUNCTION(hal, ar5211, queryPSPollSupport); + AR5K_HAL_FUNCTION(hal, ar5211, initPSPoll); + AR5K_HAL_FUNCTION(hal, ar5211, enablePSPoll); + AR5K_HAL_FUNCTION(hal, ar5211, disablePSPoll); + + /* + * Beacon functions + */ + AR5K_HAL_FUNCTION(hal, ar5211, beaconInit); + AR5K_HAL_FUNCTION(hal, ar5211, setStationBeaconTimers); + AR5K_HAL_FUNCTION(hal, ar5211, resetStationBeaconTimers); + AR5K_HAL_FUNCTION(hal, ar5211, waitForBeaconDone); + + /* + * Interrupt functions + */ + AR5K_HAL_FUNCTION(hal, ar5211, isInterruptPending); + AR5K_HAL_FUNCTION(hal, ar5211, getPendingInterrupts); + AR5K_HAL_FUNCTION(hal, ar5211, getInterrupts); + AR5K_HAL_FUNCTION(hal, ar5211, setInterrupts); + + /* + * Chipset functions (ar5k-specific, non-HAL) + */ + AR5K_HAL_FUNCTION(hal, ar5211, get_capabilities); + AR5K_HAL_FUNCTION(hal, ar5211, radar_alert); + + /* + * EEPROM access + */ + AR5K_HAL_FUNCTION(hal, ar5211, eeprom_is_busy); + AR5K_HAL_FUNCTION(hal, ar5211, eeprom_read); + AR5K_HAL_FUNCTION(hal, ar5211, eeprom_write); +} + +struct ath_hal * +ar5k_ar5211_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_ar5211_fill(hal); + + /* Bring device out of sleep and reset it's units */ + if (ar5k_ar5211_nic_wakeup(hal, AR5K_INIT_MODE) != AH_TRUE) + return (NULL); + + /* Get MAC, PHY and RADIO revisions */ + srev = AR5K_REG_READ(AR5K_AR5211_SREV) & AR5K_AR5211_SREV_M; + hal->ah_mac_version = srev & AR5K_AR5211_SREV_VERSION; + hal->ah_mac_revision = srev & AR5K_AR5211_SREV_REVISION; + hal->ah_phy_revision = AR5K_REG_READ(AR5K_AR5211_PHY_CHIP_ID) & + 0x00ffffffff; + + hal->ah_radio_5ghz_revision = + ar5k_ar5211_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_ar5211_radio_revision(hal, HAL_CHIP_2GHZ); + + /* Identify the chipset (this has to be done in an early step) */ + hal->ah_version = AR5K_AR5211; + hal->ah_radio = AR5K_AR5111; + hal->ah_phy = AR5K_AR5211_PHY(0); + + memset(&mac, 0xff, sizeof(mac)); + ar5k_ar5211_writeAssocid(hal, mac, 0, 0); + ar5k_ar5211_getMacAddress(hal, mac); + ar5k_ar5211_setPCUConfig(hal); + + return (hal); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_RXDP); + + /* + * Reset the device and wait until success + */ + AR5K_REG_WRITE(AR5K_AR5211_RC, val); + + /* Wait at least 128 PCI clocks */ + AR5K_DELAY(15); + + val &= + AR5K_AR5211_RC_PCU | AR5K_AR5211_RC_BB; + + mask &= + AR5K_AR5211_RC_PCU | AR5K_AR5211_RC_BB; + + ret = ar5k_register_timeout(hal, AR5K_AR5211_RC, mask, val, AH_FALSE); + + /* + * Reset configuration register + */ + if ((val & AR5K_AR5211_RC_PCU) == 0) + AR5K_REG_WRITE(AR5K_AR5211_CFG, AR5K_AR5211_INIT_CFG); + + return (ret); +} + +HAL_BOOL +ar5k_ar5211_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 (flags & IEEE80211_CHAN_2GHZ) { + mode |= AR5K_AR5211_PHY_MODE_FREQ_2GHZ; + clock |= AR5K_AR5211_PHY_PLL_44MHZ; + } else if (flags & IEEE80211_CHAN_5GHZ) { + mode |= AR5K_AR5211_PHY_MODE_FREQ_5GHZ; + clock |= AR5K_AR5211_PHY_PLL_40MHZ; + } else { + AR5K_PRINT("invalid radio frequency mode\n"); + return (AH_FALSE); + } + + if ((flags & IEEE80211_CHAN_CCK) || + (flags & IEEE80211_CHAN_DYN)) { + /* Dynamic OFDM/CCK is not supported by the AR5211 */ + mode |= AR5K_AR5211_PHY_MODE_MOD_CCK; + } else if (flags & IEEE80211_CHAN_OFDM) { + mode |= AR5K_AR5211_PHY_MODE_MOD_OFDM; + } else { + AR5K_PRINT("invalid radio frequency mode\n"); + return (AH_FALSE); + } + + if (flags & IEEE80211_CHAN_TURBO) { + turbo = AR5K_AR5211_PHY_TURBO_MODE | + AR5K_AR5211_PHY_TURBO_SHORT; + } + + /* + * Reset and wakeup the device + */ + + /* ...reset chipset and PCI device */ + if (ar5k_ar5211_nic_reset(hal, + AR5K_AR5211_RC_CHIP | AR5K_AR5211_RC_PCI) == AH_FALSE) { + AR5K_PRINT("failed to reset the AR5211 + PCI chipset\n"); + return (AH_FALSE); + } + + /* ...wakeup */ + if (ar5k_ar5211_setPowerMode(hal, + HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) { + AR5K_PRINT("failed to resume the AR5211 (again)\n"); + return (AH_FALSE); + } + + /* ...final warm reset */ + if (ar5k_ar5211_nic_reset(hal, 0) == AH_FALSE) { + AR5K_PRINT("failed to warm reset the AR5211\n"); + return (AH_FALSE); + } + + /* ...set the PHY operating mode */ + AR5K_REG_WRITE(AR5K_AR5211_PHY_PLL, clock); + AR5K_DELAY(300); + + AR5K_REG_WRITE(AR5K_AR5211_PHY_MODE, mode); + AR5K_REG_WRITE(AR5K_AR5211_PHY_TURBO, turbo); + + return (AH_TRUE); +} + +u_int16_t +ar5k_ar5211_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_AR5211_PHY(0), AR5K_AR5211_PHY_SHIFT_2GHZ); + break; + case HAL_CHIP_5GHZ: + AR5K_REG_WRITE(AR5K_AR5211_PHY(0), AR5K_AR5211_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_AR5211_PHY(0x34), 0x00001c16); + + for (i = 0; i < 8; i++) + AR5K_REG_WRITE(AR5K_AR5211_PHY(0x20), 0x00010000); + srev = (AR5K_REG_READ(AR5K_AR5211_PHY(0x100)) >> 24) & 0xff; + + ret = ar5k_bitswap(((srev & 0xf0) >> 4) | ((srev & 0x0f) << 4), 8); + + /* Reset to the 5GHz mode */ + AR5K_REG_WRITE(AR5K_AR5211_PHY(0), AR5K_AR5211_PHY_SHIFT_5GHZ); + + return (ret); +} + +const HAL_RATE_TABLE * +ar5k_ar5211_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_ar5211_detach(hal) + struct ath_hal *hal; +{ + /* + * Free HAL structure, assume interrupts are down + */ + free(hal, M_DEVBUF); +} + +HAL_BOOL +ar5k_ar5211_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, mode, freq, ee_mode, ant[2]; + + if (ar5k_ar5211_nic_wakeup(hal, channel->c_channel_flags) == AH_FALSE) + return (AH_FALSE); + + /* + * Initialize operating mode + */ + hal->ah_op_mode = op_mode; + + 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 { + AR5K_PRINTF("invalid channel: %d\n", channel->c_channel); + return (AH_FALSE); + } + + /* PHY access enable */ + AR5K_REG_WRITE(AR5K_AR5211_PHY(0), AR5K_AR5211_PHY_SHIFT_5GHZ); + + /* + * Write initial register settings + */ + for (i = 0; i < AR5K_ELEMENTS(ar5211_ini); i++) { + if (change_channel == AH_TRUE && + ar5211_ini[i].ini_register >= AR5K_AR5211_PCU_MIN && + ar5211_ini[i].ini_register <= AR5K_AR5211_PCU_MAX) + continue; + + AR5K_REG_WRITE((u_int32_t)ar5211_ini[i].ini_register, + ar5211_ini[i].ini_value); + } + + /* + * Write initial mode settings + */ + for (i = 0; i < AR5K_ELEMENTS(ar5211_mode); i++) { + AR5K_REG_WRITE((u_int32_t)ar5211_mode[i].mode_register, + ar5211_mode[i].mode_value[mode]); + } + + /* + * Write initial RF gain settings + */ + if (ar5k_rfgain(hal, AR5K_INI_PHY_5111, freq) == AH_FALSE) + return (AH_FALSE); + + AR5K_DELAY(1000); + + /* + * Configure additional registers + */ + + /* Set antenna mode */ + AR5K_REG_MASKED_BITS(AR5K_AR5211_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_AR5211_PHY_ANT_SWITCH_TABLE_0, + hal->ah_antenna[ee_mode][ant[0]]); + AR5K_REG_WRITE(AR5K_AR5211_PHY_ANT_SWITCH_TABLE_1, + hal->ah_antenna[ee_mode][ant[1]]); + + /* Commit values from EEPROM */ + AR5K_REG_WRITE_BITS(AR5K_AR5211_PHY_FC, + AR5K_AR5211_PHY_FC_TX_CLIP, ee->ee_tx_clip); + + AR5K_REG_WRITE(AR5K_AR5211_PHY(0x5a), + AR5K_AR5211_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode])); + + AR5K_REG_MASKED_BITS(AR5K_AR5211_PHY(0x11), + (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, 0xffffc07f); + AR5K_REG_MASKED_BITS(AR5K_AR5211_PHY(0x12), + (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, 0xfffc0fff); + AR5K_REG_MASKED_BITS(AR5K_AR5211_PHY(0x14), + (ee->ee_adc_desired_size[ee_mode] & 0x00ff) | + ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00), 0xffff0000); + + AR5K_REG_WRITE(AR5K_AR5211_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_AR5211_PHY(0x0a), + ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff); + AR5K_REG_MASKED_BITS(AR5K_AR5211_PHY(0x19), + (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff); + AR5K_REG_MASKED_BITS(AR5K_AR5211_PHY(0x49), 4, 0xffffff01); + + AR5K_REG_ENABLE_BITS(AR5K_AR5211_PHY_IQ, + AR5K_AR5211_PHY_IQ_CORR_ENABLE | + (ee->ee_i_cal[ee_mode] << AR5K_AR5211_PHY_IQ_CORR_Q_I_COFF_S) | + ee->ee_q_cal[ee_mode]); + + /* Misc */ + memset(&mac, 0xff, sizeof(mac)); + ar5k_ar5211_writeAssocid(hal, mac, 0, 0); + ar5k_ar5211_setPCUConfig(hal); + AR5K_REG_WRITE(AR5K_AR5211_PISR, 0xffffffff); + AR5K_REG_WRITE(AR5K_AR5211_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_AR5211_PHY_ACTIVE, AR5K_AR5211_PHY_ENABLE); + + data = AR5K_REG_READ(AR5K_AR5211_PHY_RX_DELAY) & + AR5K_AR5211_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_AR5211_PHY_AGCCTL, + AR5K_AR5211_PHY_AGCCTL_NF | + AR5K_AR5211_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_AR5211_PHY_IQ, + AR5K_AR5211_PHY_IQ_CAL_NUM_LOG_MAX, 15); + AR5K_REG_ENABLE_BITS(AR5K_AR5211_PHY_IQ, + AR5K_AR5211_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_AR5211_DCU_QCUMASK(i), i); + if (ar5k_ar5211_resetTxQueue(hal, i) == AH_FALSE) { + AR5K_PRINTF("failed to reset TX queue #%d\n", i); + return (AH_FALSE); + } + } + + /* Pre-enable interrupts */ + ar5k_ar5211_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_ar5211_gpioCfgInput(hal, 0); + if ((hal->ah_gpio[0] = ar5k_ar5211_gpioGet(hal, 0)) == 0) + ar5k_ar5211_gpioSetIntr(hal, 0, 1); + else + ar5k_ar5211_gpioSetIntr(hal, 0, 0); + } + + /* + * Disable beacons and reset the register + */ + AR5K_REG_DISABLE_BITS(AR5K_AR5211_BEACON, + AR5K_AR5211_BEACON_ENABLE | AR5K_AR5211_BEACON_RESET_TSF); + + return (AH_TRUE); +} + +void +ar5k_ar5211_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_AR5211_STA_ID1_ADHOC | + AR5K_AR5211_STA_ID1_DESC_ANTENNA; + break; + + case IEEE80211_M_HOSTAP: + pcu_reg |= AR5K_AR5211_STA_ID1_AP | + AR5K_AR5211_STA_ID1_RTS_DEFAULT_ANTENNA; + break; + + case IEEE80211_M_STA: + case IEEE80211_M_MONITOR: + pcu_reg |= AR5K_AR5211_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_AR5211_STA_ID0, low_id); + AR5K_REG_WRITE(AR5K_AR5211_STA_ID1, pcu_reg | high_id); + + return; +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_PHY_IQ) & AR5K_AR5211_PHY_IQ_RUN) + goto done; + + hal->ah_calibration = AH_FALSE; + + iq_corr = AR5K_REG_READ(AR5K_AR5211_PHY_IQRES_CAL_CORR); + i_pwr = AR5K_REG_READ(AR5K_AR5211_PHY_IQRES_CAL_PWR_I); + q_pwr = AR5K_REG_READ(AR5K_AR5211_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_AR5211_PHY_IQ, + AR5K_AR5211_PHY_IQ_CORR_ENABLE | + ((u_int32_t)q_coff) | + ((u_int32_t)i_coff << AR5K_AR5211_PHY_IQ_CORR_Q_I_COFF_S)); + + done: + /* Start noise floor calibration */ + AR5K_REG_ENABLE_BITS(AR5K_AR5211_PHY_AGCCTL, + AR5K_AR5211_PHY_AGCCTL_NF); + + return (AH_TRUE); +} + +/* + * Transmit functions + */ + +HAL_BOOL +ar5k_ar5211_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_ar5211_setInterrupts(hal, hal->ah_imr & ~HAL_INT_GLOBAL); + + trigger_level = AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5211_TXCFG), + AR5K_AR5211_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_AR5211_TXCFG, + AR5K_AR5211_TXCFG_TXFULL, trigger_level); + status = AH_TRUE; + + done: + /* + * Restore interrupt mask + */ + ar5k_ar5211_setInterrupts(hal, imr); + + return (status); +} + +int +ar5k_ar5211_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_ar5211_setTxQueueProps(hal, queue, queue_info) + != AH_TRUE) + return (-1); + } + + AR5K_Q_ENABLE_BITS(hal->ah_txq_interrupts, queue); + + return (queue); +} + +HAL_BOOL +ar5k_ar5211_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_ar5211_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_ar5211_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_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_AR5211_DCU_RETRY_LMT_SH_RETRY ? + AR5K_AR5211_DCU_RETRY_LMT_SH_RETRY : retry_lg; + } else { + retry_lg = AR5K_INIT_LG_RETRY; + retry_sh = AR5K_INIT_SH_RETRY; + } + + AR5K_REG_WRITE(AR5K_AR5211_DCU_RETRY_LMT(queue), + AR5K_REG_SM(AR5K_INIT_SLG_RETRY, + AR5K_AR5211_DCU_RETRY_LMT_SLG_RETRY) + | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, + AR5K_AR5211_DCU_RETRY_LMT_SSH_RETRY) + | AR5K_REG_SM(retry_lg, AR5K_AR5211_DCU_RETRY_LMT_LG_RETRY) + | AR5K_REG_SM(retry_sh, AR5K_AR5211_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_AR5211_DCU_LCL_IFS(queue), + AR5K_REG_SM(cw_min, AR5K_AR5211_DCU_LCL_IFS_CW_MIN) | + AR5K_REG_SM(cw_max, AR5K_AR5211_DCU_LCL_IFS_CW_MAX) | + AR5K_REG_SM(hal->ah_aifs + tq->tqi_aifs, + AR5K_AR5211_DCU_LCL_IFS_AIFS)); + + /* + * Set misc registers + */ + AR5K_REG_WRITE(AR5K_AR5211_QCU_MISC(queue), + AR5K_AR5211_QCU_MISC_DCU_EARLY); + + if (tq->tqi_cbr_period) { + AR5K_REG_WRITE(AR5K_AR5211_QCU_CBRCFG(queue), + AR5K_REG_SM(tq->tqi_cbr_period, + AR5K_AR5211_QCU_CBRCFG_INTVAL) | + AR5K_REG_SM(tq->tqi_cbr_overflow_limit, + AR5K_AR5211_QCU_CBRCFG_ORN_THRES)); + AR5K_REG_ENABLE_BITS(AR5K_AR5211_QCU_MISC(queue), + AR5K_AR5211_QCU_MISC_FRSHED_CBR); + if (tq->tqi_cbr_overflow_limit) + AR5K_REG_ENABLE_BITS(AR5K_AR5211_QCU_MISC(queue), + AR5K_AR5211_QCU_MISC_CBR_THRES_ENABLE); + } + + if (tq->tqi_ready_time) { + AR5K_REG_WRITE(AR5K_AR5211_QCU_RDYTIMECFG(queue), + AR5K_REG_SM(tq->tqi_ready_time, + AR5K_AR5211_QCU_RDYTIMECFG_INTVAL) | + AR5K_AR5211_QCU_RDYTIMECFG_ENABLE); + } + + if (tq->tqi_burst_time) { + AR5K_REG_WRITE(AR5K_AR5211_DCU_CHAN_TIME(queue), + AR5K_REG_SM(tq->tqi_burst_time, + AR5K_AR5211_DCU_CHAN_TIME_DUR) | + AR5K_AR5211_DCU_CHAN_TIME_ENABLE); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) { + AR5K_REG_ENABLE_BITS(AR5K_AR5211_QCU_MISC(queue), + AR5K_AR5211_QCU_MISC_TXE); + } + } + + if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) { + AR5K_REG_WRITE(AR5K_AR5211_DCU_MISC(queue), + AR5K_AR5211_DCU_MISC_POST_FR_BKOFF_DIS); + } + + if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { + AR5K_REG_WRITE(AR5K_AR5211_DCU_MISC(queue), + AR5K_AR5211_DCU_MISC_BACKOFF_FRAG); + } + + /* + * Set registers by queue type + */ + switch (tq->tqi_type) { + case HAL_TX_QUEUE_BEACON: + AR5K_REG_ENABLE_BITS(AR5K_AR5211_QCU_MISC(queue), + AR5K_AR5211_QCU_MISC_FRSHED_DBA_GT | + AR5K_AR5211_QCU_MISC_CBREXP_BCN | + AR5K_AR5211_QCU_MISC_BCN_ENABLE); + + AR5K_REG_ENABLE_BITS(AR5K_AR5211_DCU_MISC(queue), + (AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_GLOBAL << + AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_GLOBAL) | + AR5K_AR5211_DCU_MISC_POST_FR_BKOFF_DIS | + AR5K_AR5211_DCU_MISC_BCN_ENABLE); + + AR5K_REG_WRITE(AR5K_AR5211_QCU_RDYTIMECFG(queue), + ((AR5K_TUNE_BEACON_INTERVAL - + (AR5K_TUNE_SW_BEACON_RESP - AR5K_TUNE_DMA_BEACON_RESP) - + AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | + AR5K_AR5211_QCU_RDYTIMECFG_ENABLE); + break; + + case HAL_TX_QUEUE_CAB: + AR5K_REG_ENABLE_BITS(AR5K_AR5211_QCU_MISC(queue), + AR5K_AR5211_QCU_MISC_FRSHED_DBA_GT | + AR5K_AR5211_QCU_MISC_CBREXP | + AR5K_AR5211_QCU_MISC_CBREXP_BCN); + + AR5K_REG_ENABLE_BITS(AR5K_AR5211_DCU_MISC(queue), + (AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_GLOBAL << + AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_GLOBAL)); + break; + + case HAL_TX_QUEUE_PSPOLL: + AR5K_REG_ENABLE_BITS(AR5K_AR5211_QCU_MISC(queue), + AR5K_AR5211_QCU_MISC_CBREXP); + break; + + case HAL_TX_QUEUE_DATA: + default: + break; + } + + /* + * Enable tx queue in the secondary interrupt mask registers + */ + AR5K_REG_WRITE(AR5K_AR5211_SIMR0, + AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5211_SIMR0_QCU_TXOK) | + AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5211_SIMR0_QCU_TXDESC)); + AR5K_REG_WRITE(AR5K_AR5211_SIMR1, + AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5211_SIMR1_QCU_TXERR)); + AR5K_REG_WRITE(AR5K_AR5211_SIMR2, + AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5211_SIMR2_QCU_TXURN)); + + return (AH_TRUE); +} + +u_int32_t +ar5k_ar5211_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_AR5211_QCU_TXDP(queue))); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_QCU_TXE, queue)) + return (AH_FALSE); + + AR5K_REG_WRITE(AR5K_AR5211_QCU_TXDP(queue), phys_addr); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_QCU_TXD, queue)) + return (AH_FALSE); + + /* Start queue */ + AR5K_REG_WRITE_Q(AR5K_AR5211_QCU_TXE, queue); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_QCU_TXD, queue); + + ret = ar5k_register_timeout(hal, AR5K_AR5211_QCU_STS(queue), + AR5K_AR5211_QCU_STS_FRMPENDCNT, 0, AH_FALSE); + + /* Clear register */ + AR5K_REG_WRITE(AR5K_AR5211_QCU_TXD, 0); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5211_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_ar5211_tx_desc *tx_desc; + + tx_desc = (struct ar5k_ar5211_tx_desc*)&desc->ds_ctl0; + + /* Clear descriptor */ + bzero(tx_desc, sizeof(struct ar5k_ar5211_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_rate = tx_rate0; + 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); + +#undef _TX_FLAGS + + /* + * WEP crap + */ + if (key_index != HAL_TXKEYIX_INVALID) { + tx_desc->encrypt_key_valid = 1; + tx_desc->encrypt_key_index = key_index; + } + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5211_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_ar5211_tx_desc *tx_desc; + + tx_desc = (struct ar5k_ar5211_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_ar5211_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; +{ + return (AH_FALSE); +} + +HAL_STATUS +ar5k_ar5211_procTxDesc(hal, desc) + struct ath_hal *hal; + struct ath_desc *desc; +{ + struct ar5k_ar5211_tx_status *tx_status; + struct ar5k_ar5211_tx_desc *tx_desc; + + tx_desc = (struct ar5k_ar5211_tx_desc*)&desc->ds_ctl0; + tx_status = (struct ar5k_ar5211_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 ? + (tx_status->rts_fail_count + 1) : 0; + desc->ds_us.tx.ts_longretry = tx_status->data_fail_count ? + (tx_status->data_fail_count + 1) : 0; + desc->ds_us.tx.ts_rssi = tx_status->ack_sig_strength; + desc->ds_us.tx.ts_antenna = 0; + desc->ds_us.tx.ts_status = 0; + desc->ds_us.tx.ts_rate = tx_desc->xmit_rate; + + 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_ar5211_hasVEOL(hal) + struct ath_hal *hal; +{ + return (AH_TRUE); +} + +/* + * Receive functions + */ + +u_int32_t +ar5k_ar5211_getRxDP(hal) + struct ath_hal *hal; +{ + return (AR5K_REG_READ(AR5K_AR5211_RXDP)); +} + +void +ar5k_ar5211_setRxDP(hal, phys_addr) + struct ath_hal *hal; + u_int32_t phys_addr; +{ + AR5K_REG_WRITE(AR5K_AR5211_RXDP, phys_addr); +} + +void +ar5k_ar5211_enableReceive(hal) + struct ath_hal *hal; +{ + AR5K_REG_WRITE(AR5K_AR5211_CR, AR5K_AR5211_CR_RXE); +} + +HAL_BOOL +ar5k_ar5211_stopDmaReceive(hal) + struct ath_hal *hal; +{ + int i; + + AR5K_REG_WRITE(AR5K_AR5211_CR, AR5K_AR5211_CR_RXD); + + /* + * It may take some time to disable the DMA receive unit + */ + for (i = 2000; + i > 0 && (AR5K_REG_READ(AR5K_AR5211_CR) & AR5K_AR5211_CR_RXE) != 0; + i--) + AR5K_DELAY(10); + + return (i > 0 ? AH_TRUE : AH_FALSE); +} + +void +ar5k_ar5211_startPcuReceive(hal) + struct ath_hal *hal; +{ + AR5K_REG_DISABLE_BITS(AR5K_AR5211_DIAG_SW, AR5K_AR5211_DIAG_SW_DIS_RX); +} + +void +ar5k_ar5211_stopPcuReceive(hal) + struct ath_hal *hal; +{ + AR5K_REG_ENABLE_BITS(AR5K_AR5211_DIAG_SW, AR5K_AR5211_DIAG_SW_DIS_RX); +} + +void +ar5k_ar5211_setMulticastFilter(hal, filter0, filter1) + struct ath_hal *hal; + u_int32_t filter0; + u_int32_t filter1; +{ + /* Set the multicat filter */ + AR5K_REG_WRITE(AR5K_AR5211_MCAST_FIL0, filter0); + AR5K_REG_WRITE(AR5K_AR5211_MCAST_FIL1, filter1); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_MCAST_FIL1, + (1 << (index - 32))); + } else { + AR5K_REG_ENABLE_BITS(AR5K_AR5211_MCAST_FIL0, + (1 << index)); + } + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_MCAST_FIL1, + (1 << (index - 32))); + } else { + AR5K_REG_DISABLE_BITS(AR5K_AR5211_MCAST_FIL0, + (1 << index)); + } + + return (AH_TRUE); +} + +u_int32_t +ar5k_ar5211_getRxFilter(hal) + struct ath_hal *hal; +{ + return (AR5K_REG_READ(AR5K_AR5211_RX_FILTER)); +} + +void +ar5k_ar5211_setRxFilter(hal, filter) + struct ath_hal *hal; + u_int32_t filter; +{ + AR5K_REG_WRITE(AR5K_AR5211_RX_FILTER, filter); +} + +HAL_BOOL +ar5k_ar5211_setupRxDesc(hal, desc, size, flags) + struct ath_hal *hal; + struct ath_desc *desc; + u_int32_t size; + u_int flags; +{ + struct ar5k_ar5211_rx_desc *rx_desc; + + /* Reset descriptor */ + desc->ds_ctl0 = 0; + desc->ds_ctl1 = 0; + bzero(&desc->ds_hw[0], sizeof(struct ar5k_ar5211_rx_status)); + + rx_desc = (struct ar5k_ar5211_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_ar5211_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_ar5211_rx_status *rx_status; + + rx_status = (struct ar5k_ar5211_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_AR5211_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; + } + + return (HAL_OK); +} + +void +ar5k_ar5211_rxMonitor(hal) + struct ath_hal *hal; +{ + AR5K_REG_ENABLE_BITS(AR5K_AR5211_RX_FILTER, + AR5K_AR5211_RX_FILTER_PROMISC); +} + +/* + * Misc functions + */ + +void +ar5k_ar5211_dumpState(hal) + struct ath_hal *hal; +{ + /* Not used */ + return; +} + +HAL_BOOL +ar5k_ar5211_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_ar5211_getMacAddress(hal, mac) + struct ath_hal *hal; + u_int8_t *mac; +{ + memcpy(mac, hal->ah_sta_id, IEEE80211_ADDR_LEN); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_STA_ID0, htole32(low_id)); + AR5K_REG_WRITE(AR5K_AR5211_STA_ID1, high_id); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5211_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_ar5211_setLedState(hal, state) + struct ath_hal *hal; + HAL_LED_STATE state; +{ + u_int32_t led; + + AR5K_REG_DISABLE_BITS(AR5K_AR5211_PCICFG, + AR5K_AR5211_PCICFG_LEDMODE | AR5K_AR5211_PCICFG_LED); + + /* + * Some blinking values, define at your wish + */ + switch (state) { + case IEEE80211_S_SCAN: + case IEEE80211_S_AUTH: + led = + AR5K_AR5211_PCICFG_LEDMODE_PROP | + AR5K_AR5211_PCICFG_LED_PEND; + break; + + case IEEE80211_S_INIT: + led = + AR5K_AR5211_PCICFG_LEDMODE_PROP | + AR5K_AR5211_PCICFG_LED_NONE; + break; + + case IEEE80211_S_ASSOC: + case IEEE80211_S_RUN: + led |= + AR5K_AR5211_PCICFG_LEDMODE_PROP | + AR5K_AR5211_PCICFG_LED_ASSOC; + break; + + default: + led |= + AR5K_AR5211_PCICFG_LEDMODE_PROM | + AR5K_AR5211_PCICFG_LED_NONE; + break; + } + + AR5K_REG_ENABLE_BITS(AR5K_AR5211_PCICFG, led); +} + +void +ar5k_ar5211_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 BSSID which triggers the "SME Join" operation + */ + memcpy(&low_id, bssid, 4); + memcpy(&high_id, bssid + 4, 2); + AR5K_REG_WRITE(AR5K_AR5211_BSS_ID0, htole32(low_id)); + AR5K_REG_WRITE(AR5K_AR5211_BSS_ID1, htole32(high_id) | + ((assoc_id & 0x3fff) << AR5K_AR5211_BSS_ID1_AID_S)); + memcpy(&hal->ah_bssid, bssid, IEEE80211_ADDR_LEN); + + if (assoc_id == 0) { + ar5k_ar5211_disablePSPoll(hal); + return; + } + + AR5K_REG_WRITE(AR5K_AR5211_BEACON, + (AR5K_REG_READ(AR5K_AR5211_BEACON) & + ~AR5K_AR5211_BEACON_TIM) | + (((tim_offset ? tim_offset + 4 : 0) << + AR5K_AR5211_BEACON_TIM_S) & + AR5K_AR5211_BEACON_TIM)); + + ar5k_ar5211_enablePSPoll(hal, NULL, 0); +} + +HAL_BOOL +ar5k_ar5211_gpioCfgOutput(hal, gpio) + struct ath_hal *hal; + u_int32_t gpio; +{ + if (gpio > AR5K_AR5211_NUM_GPIO) + return (AH_FALSE); + + AR5K_REG_WRITE(AR5K_AR5211_GPIOCR, + (AR5K_REG_READ(AR5K_AR5211_GPIOCR) &~ AR5K_AR5211_GPIOCR_ALL(gpio)) + | AR5K_AR5211_GPIOCR_ALL(gpio)); + + return (AH_TRUE); +} + +HAL_BOOL +ar5k_ar5211_gpioCfgInput(hal, gpio) + struct ath_hal *hal; + u_int32_t gpio; +{ + if (gpio > AR5K_AR5211_NUM_GPIO) + return (AH_FALSE); + + AR5K_REG_WRITE(AR5K_AR5211_GPIOCR, + (AR5K_REG_READ(AR5K_AR5211_GPIOCR) &~ AR5K_AR5211_GPIOCR_ALL(gpio)) + | AR5K_AR5211_GPIOCR_NONE(gpio)); + + return (AH_TRUE); +} + +u_int32_t +ar5k_ar5211_gpioGet(hal, gpio) + struct ath_hal *hal; + u_int32_t gpio; +{ + if (gpio > AR5K_AR5211_NUM_GPIO) + return (0xffffffff); + + /* GPIO input magic */ + return (((AR5K_REG_READ(AR5K_AR5211_GPIODI) & + AR5K_AR5211_GPIODI_M) >> gpio) & 0x1); +} + +HAL_BOOL +ar5k_ar5211_gpioSet(hal, gpio, val) + struct ath_hal *hal; + u_int32_t gpio; + u_int32_t val; +{ + u_int32_t data; + + if (gpio > AR5K_AR5211_NUM_GPIO) + return (0xffffffff); + + /* GPIO output magic */ + data = AR5K_REG_READ(AR5K_AR5211_GPIODO); + + data &= ~(1 << gpio); + data |= (val&1) << gpio; + + AR5K_REG_WRITE(AR5K_AR5211_GPIODO, data); + + return (AH_TRUE); +} + +void +ar5k_ar5211_gpioSetIntr(hal, gpio, interrupt_level) + struct ath_hal *hal; + u_int gpio; + u_int32_t interrupt_level; +{ + u_int32_t data; + + if (gpio > AR5K_AR5211_NUM_GPIO) + return; + + /* + * Set the GPIO interrupt + */ + data = (AR5K_REG_READ(AR5K_AR5211_GPIOCR) & + ~(AR5K_AR5211_GPIOCR_INT_SEL(gpio) | AR5K_AR5211_GPIOCR_INT_SELH | + AR5K_AR5211_GPIOCR_INT_ENA | AR5K_AR5211_GPIOCR_ALL(gpio))) | + (AR5K_AR5211_GPIOCR_INT_SEL(gpio) | AR5K_AR5211_GPIOCR_INT_ENA); + + AR5K_REG_WRITE(AR5K_AR5211_GPIOCR, + interrupt_level ? data : (data | AR5K_AR5211_GPIOCR_INT_SELH)); + + hal->ah_imr |= AR5K_AR5211_PIMR_GPIO; + + /* Enable GPIO interrupts */ + AR5K_REG_ENABLE_BITS(AR5K_AR5211_PIMR, AR5K_AR5211_PIMR_GPIO); +} + +u_int32_t +ar5k_ar5211_getTsf32(hal) + struct ath_hal *hal; +{ + return (AR5K_REG_READ(AR5K_AR5211_TSF_L32)); +} + +u_int64_t +ar5k_ar5211_getTsf64(hal) + struct ath_hal *hal; +{ + u_int64_t tsf = AR5K_REG_READ(AR5K_AR5211_TSF_U32); + + return (AR5K_REG_READ(AR5K_AR5211_TSF_L32) | (tsf << 32)); +} + +void +ar5k_ar5211_resetTsf(hal) + struct ath_hal *hal; +{ + AR5K_REG_ENABLE_BITS(AR5K_AR5211_BEACON, + AR5K_AR5211_BEACON_RESET_TSF); +} + +u_int16_t +ar5k_ar5211_getRegDomain(hal) + struct ath_hal *hal; +{ + return (ar5k_get_regdomain(hal)); +} + +HAL_BOOL +ar5k_ar5211_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_ar5211_eeprom_read(hal, AR5K_EEPROM_MAGIC, &magic) != 0) + return (AH_FALSE); + + return (magic == AR5K_EEPROM_MAGIC_VALUE ? AH_TRUE : AH_FALSE); +} + +void +ar5k_ar5211_updateMibCounters(hal, statistics) + struct ath_hal *hal; + HAL_MIB_STATS *statistics; +{ + statistics->ackrcv_bad += AR5K_REG_READ(AR5K_AR5211_ACK_FAIL); + statistics->rts_bad += AR5K_REG_READ(AR5K_AR5211_RTS_FAIL); + statistics->rts_good += AR5K_REG_READ(AR5K_AR5211_RTS_OK); + statistics->fcs_bad += AR5K_REG_READ(AR5K_AR5211_FCS_FAIL); + statistics->beacons += AR5K_REG_READ(AR5K_AR5211_BEACON_CNT); +} + +HAL_RFGAIN +ar5k_ar5211_getRfGain(hal) + struct ath_hal *hal; +{ + return (HAL_RFGAIN_INACTIVE); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_DCU_GBL_IFS_SLOT, + ar5k_htoclock(slot_time, hal->ah_turbo)); + + return (AH_TRUE); +} + +u_int +ar5k_ar5211_getSlotTime(hal) + struct ath_hal *hal; +{ + return (ar5k_clocktoh(AR5K_REG_READ(AR5K_AR5211_DCU_GBL_IFS_SLOT) & + 0xffff, hal->ah_turbo)); +} + +HAL_BOOL +ar5k_ar5211_setAckTimeout(hal, timeout) + struct ath_hal *hal; + u_int timeout; +{ + if (ar5k_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_AR5211_TIME_OUT_ACK), + hal->ah_turbo) <= timeout) + return (AH_FALSE); + + AR5K_REG_WRITE_BITS(AR5K_AR5211_TIME_OUT, AR5K_AR5211_TIME_OUT_ACK, + ar5k_htoclock(timeout, hal->ah_turbo)); + + return (AH_TRUE); +} + +u_int +ar5k_ar5211_getAckTimeout(hal) + struct ath_hal *hal; +{ + return (ar5k_clocktoh(AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5211_TIME_OUT), + AR5K_AR5211_TIME_OUT_ACK), hal->ah_turbo)); +} + +HAL_BOOL +ar5k_ar5211_setCTSTimeout(hal, timeout) + struct ath_hal *hal; + u_int timeout; +{ + if (ar5k_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_AR5211_TIME_OUT_CTS), + hal->ah_turbo) <= timeout) + return (AH_FALSE); + + AR5K_REG_WRITE_BITS(AR5K_AR5211_TIME_OUT, AR5K_AR5211_TIME_OUT_CTS, + ar5k_htoclock(timeout, hal->ah_turbo)); + + return (AH_TRUE); +} + +u_int +ar5k_ar5211_getCTSTimeout(hal) + struct ath_hal *hal; +{ + return (ar5k_clocktoh(AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5211_TIME_OUT), + AR5K_AR5211_TIME_OUT_CTS), hal->ah_turbo)); +} + +/* + * Key table (WEP) functions + */ + +HAL_BOOL +ar5k_ar5211_isHwCipherSupported(hal, cipher) + struct ath_hal *hal; + HAL_CIPHER cipher; +{ + /* + * The AR5211 only supports WEP + */ + if (cipher == HAL_CIPHER_WEP) + return (AH_TRUE); + + return (AH_FALSE); +} + +u_int32_t +ar5k_ar5211_getKeyCacheSize(hal) + struct ath_hal *hal; +{ + return (AR5K_AR5211_KEYTABLE_SIZE); +} + +HAL_BOOL +ar5k_ar5211_resetKeyCacheEntry(hal, entry) + struct ath_hal *hal; + u_int16_t entry; +{ + int i; + + AR5K_ASSERT_ENTRY(entry, AR5K_AR5211_KEYTABLE_SIZE); + + for (i = 0; i < AR5K_AR5211_KEYCACHE_SIZE; i++) + AR5K_REG_WRITE(AR5K_AR5211_KEYTABLE(entry) + (i * 4), 0); + + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5211_isKeyCacheEntryValid(hal, entry) + struct ath_hal *hal; + u_int16_t entry; +{ + int offset; + + AR5K_ASSERT_ENTRY(entry, AR5K_AR5211_KEYTABLE_SIZE); + + /* + * Check the validation flag at the end of the entry + */ + offset = (AR5K_AR5211_KEYCACHE_SIZE - 1) * 4; + if (AR5K_REG_READ(AR5K_AR5211_KEYTABLE(entry) + offset) & + AR5K_AR5211_KEYTABLE_VALID) + return AH_TRUE; + + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_KEYCACHE_SIZE - 2; + u_int32_t key_v[elements]; + int i, offset = 0; + + AR5K_ASSERT_ENTRY(entry, AR5K_AR5211_KEYTABLE_SIZE); + + /* + * Store the key type in the last field + */ + switch (keyval->wk_len) { + case 5: + key_v[elements - 1] = AR5K_AR5211_KEYTABLE_TYPE_40; + break; + + case 13: + key_v[elements - 1] = AR5K_AR5211_KEYTABLE_TYPE_104; + break; + + case 16: + key_v[elements - 1] = AR5K_AR5211_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_AR5211_KEYTABLE(entry) + (i * 4), key_v[i]); + } + + return (ar5k_ar5211_setKeyCacheEntryMac(hal, entry, mac)); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_KEYTABLE_SIZE); + + offset = AR5K_AR5211_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_AR5211_KEYTABLE(entry) + (offset++ * 4), + htole32(low_id)); + AR5K_REG_WRITE(AR5K_AR5211_KEYTABLE(entry) + (offset * 4), high_id); + + return (AH_TRUE); +} + +/* + * Power management functions + */ + +HAL_BOOL +ar5k_ar5211_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_AR5211_SCR, + AR5K_AR5211_SCR_SLE | sleep_duration); + } + break; + + case HAL_PM_FULL_SLEEP: + if (set_chip == AH_TRUE) { + AR5K_REG_WRITE(AR5K_AR5211_SCR, + AR5K_AR5211_SCR_SLE_SLP); + } + break; + + case HAL_PM_AWAKE: + if (set_chip == AH_FALSE) + goto commit; + + AR5K_REG_WRITE(AR5K_AR5211_SCR, AR5K_AR5211_SCR_SLE_WAKE); + + for (i = 5000; i > 0; i--) { + /* Check if the AR5211 did wake up */ + if ((AR5K_REG_READ(AR5K_AR5211_PCICFG) & + AR5K_AR5211_PCICFG_SPWR_DN) == 0) + break; + + /* Wait a bit and retry */ + AR5K_DELAY(200); + AR5K_REG_WRITE(AR5K_AR5211_SCR, + AR5K_AR5211_SCR_SLE_WAKE); + } + + /* Fail if the AR5211 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_AR5211_STA_ID1, + AR5K_AR5211_STA_ID1_DEFAULT_ANTENNA); + AR5K_REG_ENABLE_BITS(AR5K_AR5211_STA_ID1, + AR5K_AR5211_STA_ID1_PWR_SV); + + return (AH_TRUE); +} + +HAL_POWER_MODE +ar5k_ar5211_getPowerMode(hal) + struct ath_hal *hal; +{ + return (hal->ah_power_mode); +} + +HAL_BOOL +ar5k_ar5211_queryPSPollSupport(hal) + struct ath_hal *hal; +{ + /* nope */ + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5211_initPSPoll(hal) + struct ath_hal *hal; +{ + /* + * Not used on the AR5211 + */ + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5211_enablePSPoll(hal, bssid, assoc_id) + struct ath_hal *hal; + u_int8_t *bssid; + u_int16_t assoc_id; +{ + return (AH_FALSE); +} + +HAL_BOOL +ar5k_ar5211_disablePSPoll(hal) + struct ath_hal *hal; +{ + return (AH_FALSE); +} + +/* + * Beacon functions + */ + +void +ar5k_ar5211_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_AR5211_TIMER0, next_beacon); + AR5K_REG_WRITE(AR5K_AR5211_TIMER1, timer1); + AR5K_REG_WRITE(AR5K_AR5211_TIMER2, timer2); + AR5K_REG_WRITE(AR5K_AR5211_TIMER3, timer3); + + AR5K_REG_WRITE(AR5K_AR5211_BEACON, interval & + (AR5K_AR5211_BEACON_PERIOD | AR5K_AR5211_BEACON_RESET_TSF | + AR5K_AR5211_BEACON_ENABLE)); +} + +void +ar5k_ar5211_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 < 1) + 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_AR5211_STA_ID1, + AR5K_AR5211_STA_ID1_DEFAULT_ANTENNA | + AR5K_AR5211_STA_ID1_PCF); + AR5K_REG_WRITE(AR5K_AR5211_CFP_PERIOD, cfp_period); + AR5K_REG_WRITE(AR5K_AR5211_CFP_DUR, state->bs_cfp_max_duration); + AR5K_REG_WRITE(AR5K_AR5211_TIMER2, + (tsf + (next_cfp == 0 ? cfp_period : next_cfp)) << 3); + } else { + /* Disable PCF mode */ + AR5K_REG_DISABLE_BITS(AR5K_AR5211_STA_ID1, + AR5K_AR5211_STA_ID1_DEFAULT_ANTENNA | + AR5K_AR5211_STA_ID1_PCF); + } + + /* + * Enable the beacon timer register + */ + AR5K_REG_WRITE(AR5K_AR5211_TIMER0, state->bs_next_beacon); + + /* + * Start the beacon timers + */ + AR5K_REG_WRITE(AR5K_AR5211_BEACON, + (AR5K_REG_READ(AR5K_AR5211_BEACON) &~ + (AR5K_AR5211_BEACON_PERIOD | AR5K_AR5211_BEACON_TIM)) | + AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, + AR5K_AR5211_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, + AR5K_AR5211_BEACON_PERIOD)); + + /* + * Write new beacon miss threshold, if it appears to be valid + */ + if ((state->bs_bmiss_threshold > (AR5K_AR5211_RSSI_THR_BMISS >> + AR5K_AR5211_RSSI_THR_BMISS_S)) && + (state->bs_bmiss_threshold & 0x00007) != 0) { + AR5K_REG_WRITE_BITS(AR5K_AR5211_RSSI_THR_M, + AR5K_AR5211_RSSI_THR_BMISS, state->bs_bmiss_threshold); + } +} + +void +ar5k_ar5211_resetStationBeaconTimers(hal) + struct ath_hal *hal; +{ + /* + * Disable beacon timer + */ + AR5K_REG_WRITE(AR5K_AR5211_TIMER0, 0); + + /* + * Disable some beacon register values + */ + AR5K_REG_DISABLE_BITS(AR5K_AR5211_STA_ID1, + AR5K_AR5211_STA_ID1_DEFAULT_ANTENNA | AR5K_AR5211_STA_ID1_PCF); + AR5K_REG_WRITE(AR5K_AR5211_BEACON, AR5K_AR5211_BEACON_PERIOD); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_QCU_STS(HAL_TX_QUEUE_BEACON), + AR5K_AR5211_QCU_STS_FRMPENDCNT, 0, AH_FALSE); + + return (ret); +} + +/* + * Interrupt handling + */ + +HAL_BOOL +ar5k_ar5211_isInterruptPending(hal) + struct ath_hal *hal; +{ + return (AR5K_REG_READ(AR5K_AR5211_INTPEND) == 0 ? AH_FALSE : AH_TRUE); +} + +HAL_BOOL +ar5k_ar5211_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_AR5211_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_AR5211_PISR_RXOK | AR5K_AR5211_PISR_RXERR)) + *interrupt_mask |= HAL_INT_RX; + + if (data & (AR5K_AR5211_PISR_TXOK | AR5K_AR5211_PISR_TXERR)) + *interrupt_mask |= HAL_INT_TX; + + if (data & (AR5K_AR5211_PISR_HIUERR)) + *interrupt_mask |= HAL_INT_FATAL; + + /* + * Special interrupt handling (not catched by the driver) + */ + if (((*interrupt_mask) & AR5K_AR5211_PISR_RXPHY) && + hal->ah_radar.r_enabled == AH_TRUE) + ar5k_radar_alert(hal); + + return (AH_TRUE); +} + +u_int32_t +ar5k_ar5211_getInterrupts(hal) + struct ath_hal *hal; +{ + /* Return the interrupt mask stored previously */ + return (hal->ah_imr); +} + +HAL_INT +ar5k_ar5211_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_AR5211_IER, AR5K_AR5211_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_AR5211_PIMR_RXOK | + AR5K_AR5211_PIMR_RXERR | + AR5K_AR5211_PIMR_RXORN | + AR5K_AR5211_PIMR_RXDESC; + + if (new_mask & HAL_INT_TX) + int_mask |= + AR5K_AR5211_PIMR_TXOK | + AR5K_AR5211_PIMR_TXERR | + AR5K_AR5211_PIMR_TXDESC | + AR5K_AR5211_PIMR_TXURN; + + if (new_mask & HAL_INT_FATAL) { + int_mask |= AR5K_AR5211_PIMR_HIUERR; + AR5K_REG_ENABLE_BITS(AR5K_AR5211_SIMR2, + AR5K_AR5211_SIMR2_MCABT | + AR5K_AR5211_SIMR2_SSERR | + AR5K_AR5211_SIMR2_DPERR); + } + + if (hal->ah_op_mode & HAL_M_HOSTAP) { + int_mask |= AR5K_AR5211_PIMR_MIB; + } else { + int_mask &= ~AR5K_AR5211_PIMR_MIB; + } + + AR5K_REG_WRITE(AR5K_AR5211_PIMR, int_mask); + + /* Store new interrupt mask */ + hal->ah_imr = new_mask; + + /* ..re-enable interrupts */ + AR5K_REG_WRITE(AR5K_AR5211_IER, AR5K_AR5211_IER_ENABLE); + + return (old_mask); +} + +/* + * Misc internal functions + */ + +HAL_BOOL +ar5k_ar5211_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 AR5211 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_AR5211_NUM_GPIO; + + /* Set number of supported TX queues */ + hal->ah_capabilities.cap_queues.q_tx_num = AR5K_AR5211_TX_NUM_QUEUES; + + return (AH_TRUE); +} + +void +ar5k_ar5211_radar_alert(hal, enable) + struct ath_hal *hal; + HAL_BOOL enable; +{ + /* + * Enable radar detection + */ + AR5K_REG_WRITE(AR5K_AR5211_IER, AR5K_AR5211_IER_DISABLE); + + if (enable == AH_TRUE) { + AR5K_REG_WRITE(AR5K_AR5211_PHY_RADAR, + AR5K_AR5211_PHY_RADAR_ENABLE); + AR5K_REG_ENABLE_BITS(AR5K_AR5211_PIMR, + AR5K_AR5211_PIMR_RXPHY); + } else { + AR5K_REG_WRITE(AR5K_AR5211_PHY_RADAR, + AR5K_AR5211_PHY_RADAR_DISABLE); + AR5K_REG_DISABLE_BITS(AR5K_AR5211_PIMR, + AR5K_AR5211_PIMR_RXPHY); + } + + AR5K_REG_WRITE(AR5K_AR5211_IER, AR5K_AR5211_IER_ENABLE); +} + +/* + * EEPROM access functions + */ + +HAL_BOOL +ar5k_ar5211_eeprom_is_busy(hal) + struct ath_hal *hal; +{ + return (AR5K_REG_READ(AR5K_AR5211_CFG) & AR5K_AR5211_CFG_EEBS ? + AH_TRUE : AH_FALSE); +} + +int +ar5k_ar5211_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_AR5211_EEPROM_BASE, (u_int8_t)offset); + AR5K_REG_ENABLE_BITS(AR5K_AR5211_EEPROM_CMD, + AR5K_AR5211_EEPROM_CMD_READ); + + for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { + status = AR5K_REG_READ(AR5K_AR5211_EEPROM_STATUS); + if (status & AR5K_AR5211_EEPROM_STAT_RDDONE) { + if (status & AR5K_AR5211_EEPROM_STAT_RDERR) + return (EIO); + *data = (u_int16_t) + (AR5K_REG_READ(AR5K_AR5211_EEPROM_DATA) & 0xffff); + return (0); + } + AR5K_DELAY(15); + } + + return (ETIMEDOUT); +} + +int +ar5k_ar5211_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_AR5211_EEPROM_CMD, + AR5K_AR5211_EEPROM_CMD_RESET); + AR5K_REG_ENABLE_BITS(AR5K_AR5211_EEPROM_CMD, + AR5K_AR5211_EEPROM_CMD_WRITE); + + /* + * Prime write pump + */ + AR5K_REG_WRITE(AR5K_AR5211_EEPROM_BASE, (u_int8_t)offset - 1); + + for (timeout = 10000; timeout > 0; timeout--) { + AR5K_DELAY(1); + status = AR5K_REG_READ(AR5K_AR5211_EEPROM_STATUS); + if (status & AR5K_AR5211_EEPROM_STAT_WRDONE) { + if (status & AR5K_AR5211_EEPROM_STAT_WRERR) + return (EIO); + return (0); + } + } + + return (ETIMEDOUT); +} diff --git a/sys/dev/ic/ar5211reg.h b/sys/dev/ic/ar5211reg.h new file mode 100644 index 00000000000..febf1bd8009 --- /dev/null +++ b/sys/dev/ic/ar5211reg.h @@ -0,0 +1,1033 @@ +/* $OpenBSD: ar5211reg.h,v 1.1 2005/02/25 22:25:30 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 + * (AR5211/AR5311). + */ + +#ifndef _AR5K_AR5211_REG_H +#define _AR5K_AR5211_REG_H + +/* + * Command register + */ +#define AR5K_AR5211_CR 0x0008 +#define AR5K_AR5211_CR_RXE 0x00000004 +#define AR5K_AR5211_CR_RXD 0x00000020 +#define AR5K_AR5211_CR_SWI 0x00000040 + +/* + * Receive queue descriptor pointer register + */ +#define AR5K_AR5211_RXDP 0x000c + +/* + * Configuration and status register + */ +#define AR5K_AR5211_CFG 0x0014 +#define AR5K_AR5211_CFG_SWTD 0x00000001 +#define AR5K_AR5211_CFG_SWTB 0x00000002 +#define AR5K_AR5211_CFG_SWRD 0x00000004 +#define AR5K_AR5211_CFG_SWRB 0x00000008 +#define AR5K_AR5211_CFG_SWRG 0x00000010 +#define AR5K_AR5211_CFG_ADHOC 0x00000020 +#define AR5K_AR5211_CFG_PHY_OK 0x00000100 +#define AR5K_AR5211_CFG_EEBS 0x00000200 +#define AR5K_AR5211_CFG_CLKGD 0x00000400 +#define AR5K_AR5211_CFG_PCI_THRES 0x00060000 +#define AR5K_AR5211_CFG_PCI_THRES_S 17 + +/* + * Interrupt enable register + */ +#define AR5K_AR5211_IER 0x0024 +#define AR5K_AR5211_IER_DISABLE 0x00000000 +#define AR5K_AR5211_IER_ENABLE 0x00000001 + +/* + * First RTS duration register + */ +#define AR5K_AR5211_RTSD0 0x0028 +#define AR5K_AR5211_RTSD0_6 0x000000ff +#define AR5K_AR5211_RTSD0_6_S 0 +#define AR5K_AR5211_RTSD0_9 0x0000ff00 +#define AR5K_AR5211_RTSD0_9_S 8 +#define AR5K_AR5211_RTSD0_12 0x00ff0000 +#define AR5K_AR5211_RTSD0_12_S 16 +#define AR5K_AR5211_RTSD0_18 0xff000000 +#define AR5K_AR5211_RTSD0_18_S 24 + +/* + * Second RTS duration register + */ +#define AR5K_AR5211_RTSD1 0x002c +#define AR5K_AR5211_RTSD1_24 0x000000ff +#define AR5K_AR5211_RTSD1_24_S 0 +#define AR5K_AR5211_RTSD1_36 0x0000ff00 +#define AR5K_AR5211_RTSD1_36_S 8 +#define AR5K_AR5211_RTSD1_48 0x00ff0000 +#define AR5K_AR5211_RTSD1_48_S 16 +#define AR5K_AR5211_RTSD1_54 0xff000000 +#define AR5K_AR5211_RTSD1_54_S 24 + +/* + * Transmit configuration register + */ +#define AR5K_AR5211_TXCFG 0x0030 +#define AR5K_AR5211_TXCFG_SDMAMR 0x00000007 +#define AR5K_AR5211_TXCFG_B_MODE 0x00000008 +#define AR5K_AR5211_TXCFG_TXFULL 0x000003f0 +#define AR5K_AR5211_TXCFG_TXFULL_S 4 +#define AR5K_AR5211_TXCFG_TXFULL_0B 0x00000000 +#define AR5K_AR5211_TXCFG_TXFULL_64B 0x00000010 +#define AR5K_AR5211_TXCFG_TXFULL_128B 0x00000020 +#define AR5K_AR5211_TXCFG_TXFULL_192B 0x00000030 +#define AR5K_AR5211_TXCFG_TXFULL_256B 0x00000040 +#define AR5K_AR5211_TXCFG_TXCONT_ENABLE 0x00000080 +#define AR5K_AR5211_TXCFG_JUMBO_TXE 0x00000400 +#define AR5K_AR5211_TXCFG_RTSRND 0x00001000 +#define AR5K_AR5211_TXCFG_FRMPAD_DIS 0x00002000 +#define AR5K_AR5211_TXCFG_RDY_DIS 0x00004000 + +/* + * Receive configuration register + */ +#define AR5K_AR5211_RXCFG 0x0034 +#define AR5K_AR5211_RXCFG_SDMAMW 0x00000007 +#define AR5K_AR5311_RXCFG_DEFAULT_ANTENNA 0x00000008 +#define AR5K_AR5211_RXCFG_ZLFDMA 0x00000010 +#define AR5K_AR5211_RXCFG_JUMBO_RXE 0x00000020 +#define AR5K_AR5211_RXCFG_JUMBO_WRAP 0x00000040 + +/* + * Receive jumbo descriptor last address register + */ +#define AR5K_AR5211_RXJLA 0x0038 + +/* + * MIB control register + */ +#define AR5K_AR5211_MIBC 0x0040 +#define AR5K_AR5211_MIBC_COW 0x00000001 +#define AR5K_AR5211_MIBC_FMC 0x00000002 +#define AR5K_AR5211_MIBC_CMC 0x00000004 +#define AR5K_AR5211_MIBC_MCS 0x00000008 + +/* + * Timeout prescale register + */ +#define AR5K_AR5211_TOPS 0x0044 +#define AR5K_AR5211_TOPS_M 0x0000ffff + +/* + * Receive timeout register (no frame received) + */ +#define AR5K_AR5211_RXNOFRM 0x0048 +#define AR5K_AR5211_RXNOFRM_M 0x000003ff + +/* + * Transmit timeout register (no frame sent) + */ +#define AR5K_AR5211_TXNOFRM 0x004c +#define AR5K_AR5211_TXNOFRM_M 0x000003ff +#define AR5K_AR5211_TXNOFRM_QCU 0x000ffc00 + +/* + * Receive frame gap timeout register + */ +#define AR5K_AR5211_RPGTO 0x0050 +#define AR5K_AR5211_RPGTO_M 0x000003ff + +/* + * Receive frame count limit register + */ +#define AR5K_AR5211_RFCNT 0x0054 +#define AR5K_AR5211_RFCNT_M 0x0000001f + +/* + * Misc settings register + */ +#define AR5K_AR5211_MISC 0x0058 +#define AR5K_AR5211_MISC_DMA_OBS_M 0x000001e0 +#define AR5K_AR5211_MISC_DMA_OBS_S 5 +#define AR5K_AR5211_MISC_MISC_OBS_M 0x00000e00 +#define AR5K_AR5211_MISC_MISC_OBS_S 9 +#define AR5K_AR5211_MISC_MAC_OBS_LSB_M 0x00007000 +#define AR5K_AR5211_MISC_MAC_OBS_LSB_S 12 +#define AR5K_AR5211_MISC_MAC_OBS_MSB_M 0x00038000 +#define AR5K_AR5211_MISC_MAC_OBS_MSB_S 15 + +/* + * QCU/DCU clock gating register + */ +#define AR5K_AR5311_QCUDCU_CLKGT +#define AR5K_AR5311_QCUDCU_CLKGT_QCU 0x0000ffff +#define AR5K_AR5311_QCUDCU_CLKGT_DCU 0x07ff0000 + +/* + * Primary interrupt status register + */ +#define AR5K_AR5211_PISR 0x0080 +#define AR5K_AR5211_PISR_RXOK 0x00000001 +#define AR5K_AR5211_PISR_RXDESC 0x00000002 +#define AR5K_AR5211_PISR_RXERR 0x00000004 +#define AR5K_AR5211_PISR_RXNOFRM 0x00000008 +#define AR5K_AR5211_PISR_RXEOL 0x00000010 +#define AR5K_AR5211_PISR_RXORN 0x00000020 +#define AR5K_AR5211_PISR_TXOK 0x00000040 +#define AR5K_AR5211_PISR_TXDESC 0x00000080 +#define AR5K_AR5211_PISR_TXERR 0x00000100 +#define AR5K_AR5211_PISR_TXNOFRM 0x00000200 +#define AR5K_AR5211_PISR_TXEOL 0x00000400 +#define AR5K_AR5211_PISR_TXURN 0x00000800 +#define AR5K_AR5211_PISR_MIB 0x00001000 +#define AR5K_AR5211_PISR_SWI 0x00002000 +#define AR5K_AR5211_PISR_RXPHY 0x00004000 +#define AR5K_AR5211_PISR_RXKCM 0x00008000 +#define AR5K_AR5211_PISR_SWBA 0x00010000 +#define AR5K_AR5211_PISR_BRSSI 0x00020000 +#define AR5K_AR5211_PISR_BMISS 0x00040000 +#define AR5K_AR5211_PISR_HIUERR 0x00080000 +#define AR5K_AR5211_PISR_BNR 0x00100000 +#define AR5K_AR5211_PISR_TIM 0x00800000 +#define AR5K_AR5211_PISR_GPIO 0x01000000 +#define AR5K_AR5211_PISR_QCBRORN 0x02000000 +#define AR5K_AR5211_PISR_QCBRURN 0x04000000 +#define AR5K_AR5211_PISR_QTRIG 0x08000000 + +/* + * Secondary interrupt status registers (0 - 4) + */ +#define AR5K_AR5211_SISR0 0x0084 +#define AR5K_AR5211_SISR0_QCU_TXOK 0x000003ff +#define AR5K_AR5211_SISR0_QCU_TXDESC 0x03ff0000 + +#define AR5K_AR5211_SISR1 0x0088 +#define AR5K_AR5211_SISR1_QCU_TXERR 0x000003ff +#define AR5K_AR5211_SISR1_QCU_TXEOL 0x03ff0000 + +#define AR5K_AR5211_SISR2 0x008c +#define AR5K_AR5211_SISR2_QCU_TXURN 0x000003ff +#define AR5K_AR5211_SISR2_MCABT 0x00100000 +#define AR5K_AR5211_SISR2_SSERR 0x00200000 +#define AR5K_AR5211_SISR2_DPERR 0x00400000 + +#define AR5K_AR5211_SISR3 0x0090 +#define AR5K_AR5211_SISR3_QCBRORN 0x000003ff +#define AR5K_AR5211_SISR3_QCBRURN 0x03ff0000 + +#define AR5K_AR5211_SISR4 0x0094 +#define AR5K_AR5211_SISR4_QTRIG 0x000003ff + +/* + * Shadow read-and-clear interrupt status registers + */ +#define AR5K_AR5211_RAC_PISR 0x00c0 +#define AR5K_AR5211_RAC_SISR0 0x00c4 +#define AR5K_AR5211_RAC_SISR1 0x00c8 +#define AR5K_AR5211_RAC_SISR2 0x00cc +#define AR5K_AR5211_RAC_SISR3 0c00d0 +#define AR5K_AR5211_RAC_SISR4 0c00d4 + +/* + * Primary interrupt mask register + */ +#define AR5K_AR5211_PIMR 0x00a0 +#define AR5K_AR5211_PIMR_RXOK 0x00000001 +#define AR5K_AR5211_PIMR_RXDESC 0x00000002 +#define AR5K_AR5211_PIMR_RXERR 0x00000004 +#define AR5K_AR5211_PIMR_RXNOFRM 0x00000008 +#define AR5K_AR5211_PIMR_RXEOL 0x00000010 +#define AR5K_AR5211_PIMR_RXORN 0x00000020 +#define AR5K_AR5211_PIMR_TXOK 0x00000040 +#define AR5K_AR5211_PIMR_TXDESC 0x00000080 +#define AR5K_AR5211_PIMR_TXERR 0x00000100 +#define AR5K_AR5211_PIMR_TXNOFRM 0x00000200 +#define AR5K_AR5211_PIMR_TXEOL 0x00000400 +#define AR5K_AR5211_PIMR_TXURN 0x00000800 +#define AR5K_AR5211_PIMR_MIB 0x00001000 +#define AR5K_AR5211_PIMR_SWI 0x00002000 +#define AR5K_AR5211_PIMR_RXPHY 0x00004000 +#define AR5K_AR5211_PIMR_RXKCM 0x00008000 +#define AR5K_AR5211_PIMR_SWBA 0x00010000 +#define AR5K_AR5211_PIMR_BRSSI 0x00020000 +#define AR5K_AR5211_PIMR_BMISS 0x00040000 +#define AR5K_AR5211_PIMR_HIUERR 0x00080000 +#define AR5K_AR5211_PIMR_BNR 0x00100000 +#define AR5K_AR5211_PIMR_TIM 0x00800000 +#define AR5K_AR5211_PIMR_GPIO 0x01000000 +#define AR5K_AR5211_PIMR_QCBRORN 0x02000000 +#define AR5K_AR5211_PIMR_QCBRURN 0x04000000 +#define AR5K_AR5211_PIMR_QTRIG 0x08000000 + +/* + * Secondary interrupt mask registers (0 - 4) + */ +#define AR5K_AR5211_SIMR0 0x00a4 +#define AR5K_AR5211_SIMR0_QCU_TXOK 0x000003ff +#define AR5K_AR5211_SIMR0_QCU_TXOK_S 0 +#define AR5K_AR5211_SIMR0_QCU_TXDESC 0x03ff0000 +#define AR5K_AR5211_SIMR0_QCU_TXDESC_S 16 + +#define AR5K_AR5211_SIMR1 0x00a8 +#define AR5K_AR5211_SIMR1_QCU_TXERR 0x000003ff +#define AR5K_AR5211_SIMR1_QCU_TXERR_S 0 +#define AR5K_AR5211_SIMR1_QCU_TXEOL 0x03ff0000 +#define AR5K_AR5211_SIMR1_QCU_TXEOL_S 16 + +#define AR5K_AR5211_SIMR2 0x00ac +#define AR5K_AR5211_SIMR2_QCU_TXURN 0x000003ff +#define AR5K_AR5211_SIMR2_QCU_TXURN_S 0 +#define AR5K_AR5211_SIMR2_MCABT 0x00100000 +#define AR5K_AR5211_SIMR2_SSERR 0x00200000 +#define AR5K_AR5211_SIMR2_DPERR 0x00400000 + +#define AR5K_AR5211_SIMR3 0x00b0 +#define AR5K_AR5211_SIMR3_QCBRORN 0x000003ff +#define AR5K_AR5211_SIMR3_QCBRORN_S 0 +#define AR5K_AR5211_SIMR3_QCBRURN 0x03ff0000 +#define AR5K_AR5211_SIMR3_QCBRURN_S 16 + +#define AR5K_AR5211_SIMR4 0x00b4 +#define AR5K_AR5211_SIMR4_QTRIG 0x000003ff +#define AR5K_AR5211_SIMR4_QTRIG_S 0 + +/* + * Queue control unit (QCU) registers (0 - 9) + */ +#define AR5K_AR5211_QCU(_n, _a) (((_n) << 2) + _a) + +/* + * QCU Transmit descriptor pointer registers + */ +#define AR5K_AR5211_QCU_TXDP(_n) AR5K_AR5211_QCU(_n, 0x0800) + +/* + * QCU Transmit enable register + */ +#define AR5K_AR5211_QCU_TXE 0x0840 + +/* + * QCU Transmit disable register + */ +#define AR5K_AR5211_QCU_TXD 0x0880 + +/* + * QCU CBR configuration registers + */ +#define AR5K_AR5211_QCU_CBRCFG(_n) AR5K_AR5211_QCU(_n, 0x08c0) +#define AR5K_AR5211_QCU_CBRCFG_INTVAL 0x00ffffff +#define AR5K_AR5211_QCU_CBRCFG_INTVAL_S 0 +#define AR5K_AR5211_QCU_CBRCFG_ORN_THRES 0xff000000 +#define AR5K_AR5211_QCU_CBRCFG_ORN_THRES_S 24 + +/* + * QCU Ready time configuration registers + */ +#define AR5K_AR5211_QCU_RDYTIMECFG(_n) AR5K_AR5211_QCU(_n, 0x0900) +#define AR5K_AR5211_QCU_RDYTIMECFG_INTVAL 0x00ffffff +#define AR5K_AR5211_QCU_RDYTIMECFG_INTVAL_S 0 +#define AR5K_AR5211_QCU_RDYTIMECFG_DURATION 0x00ffffff +#define AR5K_AR5211_QCU_RDYTIMECFG_ENABLE 0x01000000 + +/* + * QCU one shot arm set registers + */ +#define AR5K_AR5211_QCU_ONESHOTARMS(_n) AR5K_AR5211_QCU(_n, 0x0940) +#define AR5K_AR5211_QCU_ONESHOTARMS_M 0x0000ffff + +/* + * QCU one shot arm clear registers + */ +#define AR5K_AR5211_QCU_ONESHOTARMC(_n) AR5K_AR5211_QCU(_n, 0x0980) +#define AR5K_AR5211_QCU_ONESHOTARMC_M 0x0000ffff + +/* + * QCU misc registers + */ +#define AR5K_AR5211_QCU_MISC(_n) AR5K_AR5211_QCU(_n, 0x09c0) +#define AR5K_AR5211_QCU_MISC_FRSHED_M 0x0000000f +#define AR5K_AR5211_QCU_MISC_FRSHED_ASAP 0 +#define AR5K_AR5211_QCU_MISC_FRSHED_CBR 1 +#define AR5K_AR5211_QCU_MISC_FRSHED_DBA_GT 2 +#define AR5K_AR5211_QCU_MISC_FRSHED_TIM_GT 3 +#define AR5K_AR5211_QCU_MISC_FRSHED_BCN_SENT_GT 4 +#define AR5K_AR5211_QCU_MISC_ONESHOT_ENABLE 0x00000010 +#define AR5K_AR5211_QCU_MISC_CBREXP 0x00000020 +#define AR5K_AR5211_QCU_MISC_CBREXP_BCN 0x00000040 +#define AR5K_AR5211_QCU_MISC_BCN_ENABLE 0x00000080 +#define AR5K_AR5211_QCU_MISC_CBR_THRES_ENABLE 0x00000100 +#define AR5K_AR5211_QCU_MISC_TXE 0x00000200 +#define AR5K_AR5211_QCU_MISC_CBR 0x00000400 +#define AR5K_AR5211_QCU_MISC_DCU_EARLY 0x00000800 + +/* + * QCU status registers + */ +#define AR5K_AR5211_QCU_STS(_n) AR5K_AR5211_QCU(_n, 0x0a00) +#define AR5K_AR5211_QCU_STS_FRMPENDCNT 0x00000003 +#define AR5K_AR5211_QCU_STS_CBREXPCNT 0x0000ff00 + +/* + * QCU ready time shutdown register + */ +#define AR5K_AR5211_QCU_RDYTIMESHDN 0x0a40 +#define AR5K_AR5211_QCU_RDYTIMESHDN_M 0x000003ff + +/* + * DCF control unit (DCU) registers (0 - 9) + */ +#define AR5K_AR5211_DCU(_n, _a) AR5K_AR5211_QCU(_n, _a) + +/* + * DCU QCU mask registers + */ +#define AR5K_AR5211_DCU_QCUMASK(_n) AR5K_AR5211_DCU(_n, 0x1000) +#define AR5K_AR5211_DCU_QCUMASK_M 0x000003ff + +/* + * DCU local IFS settings register + */ +#define AR5K_AR5211_DCU_LCL_IFS(_n) AR5K_AR5211_DCU(_n, 0x1040) +#define AR5K_AR5211_DCU_LCL_IFS_CW_MIN 0x000003ff +#define AR5K_AR5211_DCU_LCL_IFS_CW_MIN_S 0 +#define AR5K_AR5211_DCU_LCL_IFS_CW_MAX 0x000ffc00 +#define AR5K_AR5211_DCU_LCL_IFS_CW_MAX_S 10 +#define AR5K_AR5211_DCU_LCL_IFS_AIFS 0x0ff00000 +#define AR5K_AR5211_DCU_LCL_IFS_AIFS_S 20 + +/* + * DCU retry limit registers + */ +#define AR5K_AR5211_DCU_RETRY_LMT(_n) AR5K_AR5211_DCU(_n, 0x1080) +#define AR5K_AR5211_DCU_RETRY_LMT_SH_RETRY 0x0000000f +#define AR5K_AR5211_DCU_RETRY_LMT_SH_RETRY_S 0 +#define AR5K_AR5211_DCU_RETRY_LMT_LG_RETRY 0x000000f0 +#define AR5K_AR5211_DCU_RETRY_LMT_LG_RETRY_S 4 +#define AR5K_AR5211_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 +#define AR5K_AR5211_DCU_RETRY_LMT_SSH_RETRY_S 8 +#define AR5K_AR5211_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 +#define AR5K_AR5211_DCU_RETRY_LMT_SLG_RETRY_S 14 + +/* + * DCU channel time registers + */ +#define AR5K_AR5211_DCU_CHAN_TIME(_n) AR5K_AR5211_DCU(_n, 0x10c0) +#define AR5K_AR5211_DCU_CHAN_TIME_ENABLE 0x00100000 +#define AR5K_AR5211_DCU_CHAN_TIME_DUR 0x000fffff +#define AR5K_AR5211_DCU_CHAN_TIME_DUR_S 0 + +/* + * DCU misc registers + */ +#define AR5K_AR5211_DCU_MISC(_n) AR5K_AR5211_DCU(_n, 0x1100) +#define AR5K_AR5211_DCU_MISC_BACKOFF 0x000007ff +#define AR5K_AR5211_DCU_MISC_BACKOFF_FRAG 0x00000200 +#define AR5K_AR5211_DCU_MISC_HCFPOLL_ENABLE 0x00000800 +#define AR5K_AR5211_DCU_MISC_BACKOFF_PERSIST 0x00001000 +#define AR5K_AR5211_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 +#define AR5K_AR5211_DCU_MISC_VIRTCOL 0x0000c000 +#define AR5K_AR5211_DCU_MISC_VIRTCOL_NORMAL 0 +#define AR5K_AR5211_DCU_MISC_VIRTCOL_MODIFIED 1 +#define AR5K_AR5211_DCU_MISC_VIRTCOL_IGNORE 2 +#define AR5K_AR5211_DCU_MISC_BCN_ENABLE 0x00010000 +#define AR5K_AR5211_DCU_MISC_ARBLOCK_CTL 0x00060000 +#define AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_S 17 +#define AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_NONE 0 +#define AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_INTFRM 1 +#define AR5K_AR5211_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 +#define AR5K_AR5211_DCU_MISC_ARBLOCK_IGNORE 0x00080000 +#define AR5K_AR5211_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 +#define AR5K_AR5211_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 +#define AR5K_AR5211_DCU_MISC_VIRT_COLL_POLICY 0x00400000 +#define AR5K_AR5211_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 +#define AR5K_AR5211_DCU_MISC_SEQNUM_CTL 0x01000000 + +/* + * DCU frame sequence number registers + */ +#define AR5K_AR5211_DCU_SEQNUM(_n) AR5K_AR5211_DCU(_n, 0x1140) +#define AR5K_AR5211_DCU_SEQNUM_M 0x00000fff +/* + * DCU global IFS SIFS registers + */ +#define AR5K_AR5211_DCU_GBL_IFS_SIFS 0x1030 +#define AR5K_AR5211_DCU_GBL_IFS_SIFS_M 0x0000ffff + +/* + * DCU global IFS slot interval registers + */ +#define AR5K_AR5211_DCU_GBL_IFS_SLOT 0x1070 +#define AR5K_AR5211_DCU_GBL_IFS_SLOT_M 0x0000ffff + +/* + * DCU global IFS EIFS registers + */ +#define AR5K_AR5211_DCU_GBL_IFS_EIFS 0x10b0 +#define AR5K_AR5211_DCU_GBL_IFS_EIFS_M 0x0000ffff + +/* + * DCU global IFS misc registers + */ +#define AR5K_AR5211_DCU_GBL_IFS_MISC 0x10f0 +#define AR5K_AR5211_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 +#define AR5K_AR5211_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 +#define AR5K_AR5211_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 +#define AR5K_AR5211_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 +#define AR5K_AR5211_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 + +/* + * DCU frame prefetch control register + */ +#define AR5K_AR5211_DCU_FP 0x1230 + +/* + * DCU transmit pause control/status register + */ +#define AR5K_AR5211_DCU_TXP 0x1270 +#define AR5K_AR5211_DCU_TXP_M 0x000003ff +#define AR5K_AR5211_DCU_TXP_STATUS 0x00010000 + +/* + * DCU transmit filter register + */ +#define AR5K_AR5211_DCU_TX_FILTER 0x1038 + +/* + * DCU clear transmit filter register + */ +#define AR5K_AR5211_DCU_TX_FILTER_CLR 0x143c + +/* + * DCU set transmit filter register + */ +#define AR5K_AR5211_DCU_TX_FILTER_SET 0x147c + +/* + * DMA size definitions + */ +typedef enum { + AR5K_AR5211_DMASIZE_4B = 0, + AR5K_AR5211_DMASIZE_8B, + AR5K_AR5211_DMASIZE_16B, + AR5K_AR5211_DMASIZE_32B, + AR5K_AR5211_DMASIZE_64B, + AR5K_AR5211_DMASIZE_128B, + AR5K_AR5211_DMASIZE_256B, + AR5K_AR5211_DMASIZE_512B +} ar5k_ar5211_dmasize_t; + +/* + * Reset control register + */ +#define AR5K_AR5211_RC 0x4000 +#define AR5K_AR5211_RC_PCU 0x00000001 +#define AR5K_AR5211_RC_BB 0x00000002 +#define AR5K_AR5211_RC_PCI 0x00000010 +#define AR5K_AR5211_RC_CHIP ( \ + AR5K_AR5211_RC_PCU | AR5K_AR5211_RC_BB | AR5K_AR5211_RC_PCI \ +) + +/* + * Sleep control register + */ +#define AR5K_AR5211_SCR 0x4004 +#define AR5K_AR5211_SCR_SLDUR 0x0000ffff +#define AR5K_AR5211_SCR_SLE 0x00030000 +#define AR5K_AR5211_SCR_SLE_S 16 +#define AR5K_AR5211_SCR_SLE_WAKE 0x00000000 +#define AR5K_AR5211_SCR_SLE_SLP 0x00010000 +#define AR5K_AR5211_SCR_SLE_ALLOW 0x00020000 +#define AR5K_AR5211_SCR_SLE_UNITS 0x00000008 + +/* + * Interrupt pending register + */ +#define AR5K_AR5211_INTPEND 0x4008 +#define AR5K_AR5211_INTPEND_M 0x00000001 + +/* + * Sleep force register + */ +#define AR5K_AR5211_SFR 0x400c +#define AR5K_AR5211_SFR_M 0x00000001 + +/* + * PCI configuration register + */ +#define AR5K_AR5211_PCICFG 0x4010 +#define AR5K_AR5211_PCICFG_CLKRUNEN 0x00000004 +#define AR5K_AR5211_PCICFG_EESIZE 0x00000018 +#define AR5K_AR5211_PCICFG_EESIZE_S 3 +#define AR5K_AR5211_PCICFG_EESIZE_4K 0 +#define AR5K_AR5211_PCICFG_EESIZE_8K 1 +#define AR5K_AR5211_PCICFG_EESIZE_16K 2 +#define AR5K_AR5211_PCICFG_EESIZE_FAIL 3 +#define AR5K_AR5211_PCICFG_LED 0x00000060 +#define AR5K_AR5211_PCICFG_LED_NONE 0x00000000 +#define AR5K_AR5211_PCICFG_LED_PEND 0x00000020 +#define AR5K_AR5211_PCICFG_LED_ASSOC 0x00000040 +#define AR5K_AR5211_PCICFG_BUS_SEL 0x00000380 +#define AR5K_AR5211_PCICFG_CBEFIX_DIS 0x00000400 +#define AR5K_AR5211_PCICFG_SL_INTEN 0x00000800 +#define AR5K_AR5211_PCICFG_SL_INPEN 0x00002800 +#define AR5K_AR5211_PCICFG_SPWR_DN 0x00010000 +#define AR5K_AR5211_PCICFG_LEDMODE 0x000e0000 +#define AR5K_AR5211_PCICFG_LEDMODE_PROP 0x00000000 +#define AR5K_AR5211_PCICFG_LEDMODE_PROM 0x00020000 +#define AR5K_AR5211_PCICFG_LEDMODE_PWR 0x00040000 +#define AR5K_AR5211_PCICFG_LEDMODE_RAND 0x00060000 +#define AR5K_AR5211_PCICFG_LEDBLINK 0x00700000 +#define AR5K_AR5211_PCICFG_LEDBLINK_S 20 +#define AR5K_AR5211_PCICFG_LEDSLOW 0x00800000 + +/* + * "General Purpose Input/Output" (GPIO) control register + */ +#define AR5K_AR5211_GPIOCR 0x4014 +#define AR5K_AR5211_GPIOCR_INT_ENA 0x00008000 +#define AR5K_AR5211_GPIOCR_INT_SELL 0x00000000 +#define AR5K_AR5211_GPIOCR_INT_SELH 0x00010000 +#define AR5K_AR5211_GPIOCR_NONE(n) (0 << ((n) * 2)) +#define AR5K_AR5211_GPIOCR_OUT0(n) (1 << ((n) * 2)) +#define AR5K_AR5211_GPIOCR_OUT1(n) (2 << ((n) * 2)) +#define AR5K_AR5211_GPIOCR_ALL(n) (3 << ((n) * 2)) +#define AR5K_AR5211_GPIOCR_INT_SEL(n) ((n) << 12) + +#define AR5K_AR5211_NUM_GPIO 6 + +/* + * "General Purpose Input/Output" (GPIO) data output register + */ +#define AR5K_AR5211_GPIODO 0x4018 + +/* + * "General Purpose Input/Output" (GPIO) data input register + */ +#define AR5K_AR5211_GPIODI 0x401c +#define AR5K_AR5211_GPIODI_M 0x0000002f + +/* + * Silicon revision register + */ +#define AR5K_AR5211_SREV 0x4020 +#define AR5K_AR5211_SREV_M 0x000000ff +#define AR5K_AR5211_SREV_REVISION 0x0000000f +#define AR5K_AR5211_SREV_VERSION 0x000000f0 + +/* + * EEPROM access registers + */ +#define AR5K_AR5211_EEPROM_BASE 0x6000 +#define AR5K_AR5211_EEPROM_DATA 0x6004 +#define AR5K_AR5211_EEPROM_CMD 0x6008 +#define AR5K_AR5211_EEPROM_CMD_READ 0x00000001 +#define AR5K_AR5211_EEPROM_CMD_WRITE 0x00000002 +#define AR5K_AR5211_EEPROM_CMD_RESET 0x00000004 +#define AR5K_AR5211_EEPROM_STATUS 0x600c +#define AR5K_AR5211_EEPROM_STAT_RDERR 0x00000001 +#define AR5K_AR5211_EEPROM_STAT_RDDONE 0x00000002 +#define AR5K_AR5211_EEPROM_STAT_WRERR 0x00000004 +#define AR5K_AR5211_EEPROM_STAT_WRDONE 0x00000008 +#define AR5K_AR5211_EEPROM_CFG 0x6010 + +/* + * AR5211 EEPROM data registers + */ +#define AR5K_AR5211_EEPROM_MAGIC 0x3d +#define AR5K_AR5211_EEPROM_MAGIC_VALUE 0x5aa5 +#define AR5K_AR5211_EEPROM_PROTECT 0x3f +#define AR5K_AR5211_EEPROM_PROTECT_128_191 0x80 +#define AR5K_AR5211_EEPROM_REG_DOMAIN 0xbf +#define AR5K_AR5211_EEPROM_INFO_BASE 0xc0 +#define AR5K_AR5211_EEPROM_INFO_VERSION \ + (AR5K_AR5211_EEPROM_INFO_BASE + 1) +#define AR5K_AR5211_EEPROM_INFO_MAX \ + (0x400 - AR5K_AR5211_EEPROM_INFO_BASE) + +/* + * PCU registers + */ + +#define AR5K_AR5211_PCU_MIN 0x8000 +#define AR5K_AR5211_PCU_MAX 0x8fff + +/* + * First station id register (MAC address in lower 32 bits) + */ +#define AR5K_AR5211_STA_ID0 0x8000 + +/* + * Second station id register (MAC address in upper 16 bits) + */ +#define AR5K_AR5211_STA_ID1 0x8004 +#define AR5K_AR5211_STA_ID1_AP 0x00010000 +#define AR5K_AR5211_STA_ID1_ADHOC 0x00020000 +#define AR5K_AR5211_STA_ID1_PWR_SV 0x00040000 +#define AR5K_AR5211_STA_ID1_NO_KEYSRCH 0x00080000 +#define AR5K_AR5211_STA_ID1_PCF 0x00100000 +#define AR5K_AR5211_STA_ID1_DEFAULT_ANTENNA 0x00200000 +#define AR5K_AR5211_STA_ID1_DESC_ANTENNA 0x00400000 +#define AR5K_AR5211_STA_ID1_RTS_DEFAULT_ANTENNA 0x00800000 +#define AR5K_AR5211_STA_ID1_ACKCTS_6MB 0x01000000 +#define AR5K_AR5211_STA_ID1_BASE_RATE_11B 0x02000000 + +/* + * First BSSID register (MAC address, lower 32bits) + */ +#define AR5K_AR5211_BSS_ID0 0x8008 + +/* + * Second BSSID register (MAC address in upper 16 bits) + * + * AID: Association ID + */ +#define AR5K_AR5211_BSS_ID1 0x800c +#define AR5K_AR5211_BSS_ID1_AID 0xffff0000 +#define AR5K_AR5211_BSS_ID1_AID_S 16 + +/* + * Backoff slot time register + */ +#define AR5K_AR5211_SLOT_TIME 0x8010 + +/* + * ACK/CTS timeout register + */ +#define AR5K_AR5211_TIME_OUT 0x8014 +#define AR5K_AR5211_TIME_OUT_ACK 0x00001fff +#define AR5K_AR5211_TIME_OUT_ACK_S 0 +#define AR5K_AR5211_TIME_OUT_CTS 0x1fff0000 +#define AR5K_AR5211_TIME_OUT_CTS_S 16 + +/* + * RSSI threshold register + */ +#define AR5K_AR5211_RSSI_THR 0x8018 +#define AR5K_AR5211_RSSI_THR_M 0x000000ff +#define AR5K_AR5211_RSSI_THR_BMISS 0x0000ff00 +#define AR5K_AR5211_RSSI_THR_BMISS_S 8 + +/* + * Transmit latency register + */ +#define AR5K_AR5211_USEC 0x801c +#define AR5K_AR5211_USEC_1 0x0000007f +#define AR5K_AR5211_USEC_1_S 0 +#define AR5K_AR5211_USEC_32 0x00003f80 +#define AR5K_AR5211_USEC_32_S 7 +#define AR5K_AR5211_USEC_TX_LATENCY 0x007fc000 +#define AR5K_AR5211_USEC_TX_LATENCY_S 14 +#define AR5K_AR5211_USEC_RX_LATENCY 0x1f800000 +#define AR5K_AR5211_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_AR5211_BEACON 0x8020 +#define AR5K_AR5211_BEACON_PERIOD 0x0000ffff +#define AR5K_AR5211_BEACON_PERIOD_S 0 +#define AR5K_AR5211_BEACON_TIM 0x007f0000 +#define AR5K_AR5211_BEACON_TIM_S 16 +#define AR5K_AR5211_BEACON_ENABLE 0x00800000 +#define AR5K_AR5211_BEACON_RESET_TSF 0x01000000 + +/* + * CFP period register + */ +#define AR5K_AR5211_CFP_PERIOD 0x8024 + +/* + * Next beacon time register + */ +#define AR5K_AR5211_TIMER0 0x8028 + +/* + * Next DMA beacon alert register + */ +#define AR5K_AR5211_TIMER1 0x802c + +/* + * Next software beacon alert register + */ +#define AR5K_AR5211_TIMER2 0x8030 + +/* + * Next ATIM window time register + */ +#define AR5K_AR5211_TIMER3 0x8034 + +/* + * CFP duration register + */ +#define AR5K_AR5211_CFP_DUR 0x8038 + +/* + * Receive filter register + */ +#define AR5K_AR5211_RX_FILTER 0x803c +#define AR5K_AR5211_RX_FILTER_UNICAST 0x00000001 +#define AR5K_AR5211_RX_FILTER_MULTICAST 0x00000002 +#define AR5K_AR5211_RX_FILTER_BROADCAST 0x00000004 +#define AR5K_AR5211_RX_FILTER_CONTROL 0x00000008 +#define AR5K_AR5211_RX_FILTER_BEACON 0x00000010 +#define AR5K_AR5211_RX_FILTER_PROMISC 0x00000020 +#define AR5K_AR5211_RX_FILTER_PHYERR 0x00000040 +#define AR5K_AR5211_RX_FILTER_RADARERR 0x00000080 + +/* + * Multicast filter register (lower 32 bits) + */ +#define AR5K_AR5211_MCAST_FIL0 0x8040 + +/* + * Multicast filter register (higher 16 bits) + */ +#define AR5K_AR5211_MCAST_FIL1 0x8044 + +/* + * PCU control register + */ +#define AR5K_AR5211_DIAG_SW 0x8048 +#define AR5K_AR5211_DIAG_SW_DIS_WEP_ACK 0x00000001 +#define AR5K_AR5211_DIAG_SW_DIS_ACK 0x00000002 +#define AR5K_AR5211_DIAG_SW_DIS_CTS 0x00000004 +#define AR5K_AR5211_DIAG_SW_DIS_ENC 0x00000008 +#define AR5K_AR5211_DIAG_SW_DIS_DEC 0x00000010 +#define AR5K_AR5211_DIAG_SW_DIS_RX 0x00000020 +#define AR5K_AR5211_DIAG_SW_LOOP_BACK 0x00000040 +#define AR5K_AR5211_DIAG_SW_CORR_FCS 0x00000080 +#define AR5K_AR5211_DIAG_SW_CHAN_INFO 0x00000100 +#define AR5K_AR5211_DIAG_SW_EN_SCRAM_SEED 0x00000200 +#define AR5K_AR5211_DIAG_SW_ECO_ENABLE 0x00000400 +#define AR5K_AR5211_DIAG_SW_SCRAM_SEED_M 0x0001fc00 +#define AR5K_AR5211_DIAG_SW_SCRAM_SEED_S 10 +#define AR5K_AR5211_DIAG_SW_FRAME_NV0 0x00020000 +#define AR5K_AR5211_DIAG_SW_OBSPT_M 0x000c0000 +#define AR5K_AR5211_DIAG_SW_OBSPT_S 18 + +/* + * TSF (clock) register (lower 32 bits) + */ +#define AR5K_AR5211_TSF_L32 0x804c + +/* + * TSF (clock) register (higher 32 bits) + */ +#define AR5K_AR5211_TSF_U32 0x8050 + +/* + * ADDAC test register + */ +#define AR5K_AR5211_ADDAC_TEST 0x8054 + +/* + * Default antenna register + */ +#define AR5K_AR5211_DEFAULT_ANTENNA 0x8058 + +/* + * Last beacon timestamp register + */ +#define AR5K_AR5211_LAST_TSTP 0x8080 + +/* + * NAV register (current) + */ +#define AR5K_AR5211_NAV 0x8084 + +/* + * RTS success register + */ +#define AR5K_AR5211_RTS_OK 0x8088 + +/* + * RTS failure register + */ +#define AR5K_AR5211_RTS_FAIL 0x808c + +/* + * ACK failure register + */ +#define AR5K_AR5211_ACK_FAIL 0x8090 + +/* + * FCS failure register + */ +#define AR5K_AR5211_FCS_FAIL 0x8094 + +/* + * Beacon count register + */ +#define AR5K_AR5211_BEACON_CNT 0x8098 + +/* + * Key table (WEP) register + */ +#define AR5K_AR5211_KEYTABLE_0 0x8800 +#define AR5K_AR5211_KEYTABLE(n) (AR5K_AR5211_KEYTABLE_0 + ((n) * 32)) +#define AR5K_AR5211_KEYTABLE_TYPE_40 0x00000000 +#define AR5K_AR5211_KEYTABLE_TYPE_104 0x00000001 +#define AR5K_AR5211_KEYTABLE_TYPE_128 0x00000003 +#define AR5K_AR5211_KEYTABLE_TYPE_AES 0x00000005 +#define AR5K_AR5211_KEYTABLE_TYPE_NULL 0x00000007 +#define AR5K_AR5211_KEYTABLE_VALID 0x00008000 + +#define AR5K_AR5211_KEYTABLE_SIZE 64 +#define AR5K_AR5211_KEYCACHE_SIZE 8 + +/* + * PHY register + */ +#define AR5K_AR5211_PHY(_n) (0x9800 + ((_n) << 2)) +#define AR5K_AR5211_PHY_SHIFT_2GHZ 0x00004007 +#define AR5K_AR5211_PHY_SHIFT_5GHZ 0x00000007 + +/* + * PHY turbo mode register + */ +#define AR5K_AR5211_PHY_TURBO 0x9804 +#define AR5K_AR5211_PHY_TURBO_MODE 0x00000001 +#define AR5K_AR5211_PHY_TURBO_SHORT 0x00000002 + +/* + * PHY agility command register + */ +#define AR5K_AR5211_PHY_AGC 0x9808 +#define AR5K_AR5211_PHY_AGC_DISABLE 0x08000000 + +/* + * PHY chip revision register + */ +#define AR5K_AR5211_PHY_CHIP_ID 0x9818 + +/* + * PHY activation register + */ +#define AR5K_AR5211_PHY_ACTIVE 0x981c +#define AR5K_AR5211_PHY_ENABLE 0x00000001 +#define AR5K_AR5211_PHY_DISABLE 0x00000002 + +/* + * PHY agility control register + */ +#define AR5K_AR5211_PHY_AGCCTL 0x9860 +#define AR5K_AR5211_PHY_AGCCTL_CAL 0x00000001 +#define AR5K_AR5211_PHY_AGCCTL_NF 0x00000002 + +/* + * PHY noise floor status register + */ +#define AR5K_AR5211_PHY_NF 0x9864 +#define AR5K_AR5211_PHY_NF_M 0x000001ff +#define AR5K_AR5211_PHY_NF_ACTIVE 0x00000100 +#define AR5K_AR5211_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_AR5211_PHY_NF_M) +#define AR5K_AR5211_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_AR5211_PHY_NF_M) + 1) +#define AR5K_AR5211_PHY_NF_SVAL(_n) (((_n) & AR5K_AR5211_PHY_NF_M) | (1 << 9)) + +/* + * PHY PLL control register + */ +#define AR5K_AR5211_PHY_PLL 0x987c +#define AR5K_AR5211_PHY_PLL_20MHZ 0x13 +#define AR5K_AR5211_PHY_PLL_40MHZ 0x18 +#define AR5K_AR5211_PHY_PLL_44MHZ 0x19 + +/* + * PHY receiver delay register + */ +#define AR5K_AR5211_PHY_RX_DELAY 0x9914 +#define AR5K_AR5211_PHY_RX_DELAY_M 0x00003fff + +/* + * PHY timing IQ control register + */ +#define AR5K_AR5211_PHY_IQ 0x9920 +#define AR5K_AR5211_PHY_IQ_CORR_Q_Q_COFF 0x0000001f +#define AR5K_AR5211_PHY_IQ_CORR_Q_I_COFF 0x000007e0 +#define AR5K_AR5211_PHY_IQ_CORR_Q_I_COFF_S 5 +#define AR5K_AR5211_PHY_IQ_CORR_ENABLE 0x00000800 +#define AR5K_AR5211_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 +#define AR5K_AR5211_PHY_IQ_CAL_NUM_LOG_MAX_S 12 +#define AR5K_AR5211_PHY_IQ_RUN 0x00010000 + +/* + * PHY PAPD probe register + */ +#define AR5K_AR5211_PHY_PAPD_PROBE 0x9930 +#define AR5K_AR5211_PHY_PAPD_PROBE_TX_PWR 0x00007e00 +#define AR5K_AR5211_PHY_PAPD_PROBE_TX_PWR_S 9 +#define AR5K_AR5211_PHY_PAPD_PROBE_TX_NEXT 0x00008000 +#define AR5K_AR5211_PHY_PAPD_PROBE_GAINF 0xfe000000 +#define AR5K_AR5211_PHY_PAPD_PROBE_GAINF_S 25 + +/* + * PHY frame control register + */ +#define AR5K_AR5211_PHY_FC 0x9944 +#define AR5K_AR5211_PHY_FC_TX_CLIP 0x00000038 +#define AR5K_AR5211_PHY_FC_TX_CLIP_S 3 + +/* + * PHY radar detection enable register + */ +#define AR5K_AR5211_PHY_RADAR 0x9954 +#define AR5K_AR5211_PHY_RADAR_DISABLE 0x00000000 +#define AR5K_AR5211_PHY_RADAR_ENABLE 0x00000001 + +/* + * PHY antenna switch table registers + */ +#define AR5K_AR5211_PHY_ANT_SWITCH_TABLE_0 0x9960 +#define AR5K_AR5211_PHY_ANT_SWITCH_TABLE_1 0x9964 + +/* + * PHY timing IQ calibration result register + */ +#define AR5K_AR5211_PHY_IQRES_CAL_PWR_I 0x9c10 +#define AR5K_AR5211_PHY_IQRES_CAL_PWR_Q 0x9c14 +#define AR5K_AR5211_PHY_IQRES_CAL_CORR 0x9c18 + +/* + * PHY current RSSI register + */ +#define AR5K_AR5211_PHY_CURRENT_RSSI 0x9c1c + +/* + * PHY mode register + */ +#define AR5K_AR5211_PHY_MODE 0xa200 +#define AR5K_AR5211_PHY_MODE_MOD 0x00000001 +#define AR5K_AR5211_PHY_MODE_MOD_OFDM 0 +#define AR5K_AR5211_PHY_MODE_MOD_CCK 1 +#define AR5K_AR5211_PHY_MODE_FREQ 0x00000002 +#define AR5K_AR5211_PHY_MODE_FREQ_5GHZ 0 +#define AR5K_AR5211_PHY_MODE_FREQ_2GHZ 2 + +/* + * Misc PHY/radio registers + */ +#define AR5K_AR5211_BB_GAIN(_n) (0x9b00 + ((_n) << 2)) +#define AR5K_AR5211_RF_GAIN(_n) (0x9a00 + ((_n) << 2)) + +#endif diff --git a/sys/dev/ic/ar5211var.h b/sys/dev/ic/ar5211var.h new file mode 100644 index 00000000000..f9d59a38186 --- /dev/null +++ b/sys/dev/ic/ar5211var.h @@ -0,0 +1,396 @@ +/* $OpenBSD: ar5211var.h,v 1.1 2005/02/25 22:25:30 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 + * (AR5211/AR5311). + */ + +#ifndef _AR5K_AR5211_VAR_H +#define _AR5K_AR5211_VAR_H + +#include <dev/ic/ar5xxx.h> + +/* + * Define a "magic" code for the AR5211 (the HAL layer wants it) + */ + +#define AR5K_AR5211_MAGIC 0x0000145b /* 5211 */ +#define AR5K_AR5211_TX_NUM_QUEUES 10 + +#if BYTE_ORDER == BIG_ENDIAN +#define AR5K_AR5211_INIT_CFG ( \ + AR5K_AR5211_CFG_SWTD | AR5K_AR5211_CFG_SWTB | \ + AR5K_AR5211_CFG_SWRD | AR5K_AR5211_CFG_SWRB | \ + AR5K_AR5211_CFG_SWRG \ +) +#else +#define AR5K_AR5211_INIT_CFG 0x00000000 +#endif + +/* + * Internal RX/TX descriptor structures + * (rX: reserved fields possibily used by future versions of the ar5k chipset) + */ + +struct ar5k_ar5211_rx_desc { + /* + * First word + */ + u_int32_t r1; + + /* + * Second word + */ + u_int32_t buf_len:12; + u_int32_t r2:1; + u_int32_t inter_req:1; + u_int32_t r3:18; +} __packed; + +struct ar5k_ar5211_rx_status { + /* + * First word + */ + u_int32_t data_len:12; + u_int32_t more:1; + u_int32_t r1:1; + u_int32_t receive_antenna:1; + u_int32_t receive_rate:4; + u_int32_t receive_sig_strength:8; + u_int32_t r2:5; + + /* + * Second word + */ + u_int32_t done:1; + u_int32_t frame_receive_ok:1; + u_int32_t crc_error:1; + u_int32_t fifo_overrun:1; + u_int32_t decrypt_crc_error:1; + u_int32_t phy_error:3; + u_int32_t key_index_valid:1; + u_int32_t key_index:6; + u_int32_t receive_timestamp:13; + u_int32_t key_cache_miss:1; + u_int32_t r3:3; +} __packed; + +#define AR5K_AR5211_DESC_RX_PHY_ERROR_NONE 0x00 +#define AR5K_AR5211_DESC_RX_PHY_ERROR_TIMING 0x20 +#define AR5K_AR5211_DESC_RX_PHY_ERROR_PARITY 0x40 +#define AR5K_AR5211_DESC_RX_PHY_ERROR_RATE 0x60 +#define AR5K_AR5211_DESC_RX_PHY_ERROR_LENGTH 0x80 +#define AR5K_AR5211_DESC_RX_PHY_ERROR_64QAM 0xa0 +#define AR5K_AR5211_DESC_RX_PHY_ERROR_SERVICE 0xc0 +#define AR5K_AR5211_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 + +struct ar5k_ar5211_tx_desc { + /* + * First word + */ + u_int32_t frame_len:12; + u_int32_t reserved_12_17:6; + u_int32_t xmit_rate:4; + 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 reserved_31:1; + + /* + * Second word + */ + 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 reserved_24_31:1; +} __packed; + +#define AR5K_AR5211_DESC_TX_XMIT_RATE_6 0xb +#define AR5K_AR5211_DESC_TX_XMIT_RATE_9 0xf +#define AR5K_AR5211_DESC_TX_XMIT_RATE_12 0xa +#define AR5K_AR5211_DESC_TX_XMIT_RATE_18 0xe +#define AR5K_AR5211_DESC_TX_XMIT_RATE_24 0x9 +#define AR5K_AR5211_DESC_TX_XMIT_RATE_36 0xd +#define AR5K_AR5211_DESC_TX_XMIT_RATE_48 0x8 +#define AR5K_AR5211_DESC_TX_XMIT_RATE_54 0xc + +#define AR5K_AR5211_DESC_TX_FRAME_TYPE_NORMAL 0x00 +#define AR5K_AR5211_DESC_TX_FRAME_TYPE_ATIM 0x04 +#define AR5K_AR5211_DESC_TX_FRAME_TYPE_PSPOLL 0x08 +#define AR5K_AR5211_DESC_TX_FRAME_TYPE_NO_DELAY 0x0c +#define AR5K_AR5211_DESC_TX_FRAME_TYPE_PIFS 0x10 + +struct ar5k_ar5211_tx_status { + /* + * First word + */ + 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; + + /* + * Second word + */ + u_int32_t done:1; + u_int32_t seq_num:12; + u_int32_t ack_sig_strength:8; + u_int32_t reserved_21_31:11; +} __packed; + +/* + * Public function prototypes + */ +extern ar5k_attach_t ar5k_ar5211_attach; + +/* + * Initial register values which have to be loaded into the + * card at boot time and after each reset. + */ + +#define AR5K_AR5211_INI { \ + { 0x000c, 0x00000000 }, \ + { 0x0028, 0x84849c9c }, \ + { 0x002c, 0x7c7c7c7c }, \ + { 0x0034, 0x00000005 }, \ + { 0x0040, 0x00000000 }, \ + { 0x0044, 0x00000008 }, \ + { 0x0048, 0x00000008 }, \ + { 0x004c, 0x00000010 }, \ + { 0x0050, 0x00000000 }, \ + { 0x0054, 0x0000001f }, \ + { 0x0800, 0x00000000 }, \ + { 0x0804, 0x00000000 }, \ + { 0x0808, 0x00000000 }, \ + { 0x080c, 0x00000000 }, \ + { 0x0810, 0x00000000 }, \ + { 0x0814, 0x00000000 }, \ + { 0x0818, 0x00000000 }, \ + { 0x081c, 0x00000000 }, \ + { 0x0820, 0x00000000 }, \ + { 0x0824, 0x00000000 }, \ + { 0x1230, 0x00000000 }, \ + { 0x8004, 0x00000000 }, \ + { 0x8008, 0x00000000 }, \ + { 0x800c, 0x00000000 }, \ + { 0x8018, 0x00000000 }, \ + { 0x8024, 0x00000000 }, \ + { 0x8028, 0x00000030 }, \ + { 0x802c, 0x0007ffff }, \ + { 0x8030, 0x01ffffff }, \ + { 0x8034, 0x00000031 }, \ + { 0x8038, 0x00000000 }, \ + { 0x803c, 0x00000000 }, \ + { 0x8040, 0x00000000 }, \ + { 0x8044, 0x00000002 }, \ + { 0x8048, 0x00000000 }, \ + { 0x8054, 0x00000000 }, \ + { 0x8058, 0x00000000 }, \ + /* PHY registers */ \ + { 0x9808, 0x00000000 }, \ + { 0x980c, 0x2d849093 }, \ + { 0x9810, 0x7d32e000 }, \ + { 0x9814, 0x00000f6b }, \ + { 0x981c, 0x00000000 }, \ + { 0x982c, 0x00026ffe }, \ + { 0x9830, 0x00000000 }, \ + { 0x983c, 0x00020100 }, \ + { 0x9840, 0x206a017a }, \ + { 0x984c, 0x1284613c }, \ + { 0x9854, 0x00000859 }, \ + { 0x9868, 0x409a4190 }, \ + { 0x986c, 0x050cb081 }, \ + { 0x9870, 0x0000000f }, \ + { 0x9874, 0x00000080 }, \ + { 0x9878, 0x0000000c }, \ + { 0x9900, 0x00000000 }, \ + { 0x9904, 0x00000000 }, \ + { 0x9908, 0x00000000 }, \ + { 0x990c, 0x00800000 }, \ + { 0x9910, 0x00000001 }, \ + { 0x991c, 0x0000092a }, \ + { 0x9920, 0x00000000 }, \ + { 0x9924, 0x00058a05 }, \ + { 0x9928, 0x00000001 }, \ + { 0x992c, 0x00000000 }, \ + { 0x9930, 0x00000000 }, \ + { 0x9934, 0x00000000 }, \ + { 0x9938, 0x00000000 }, \ + { 0x993c, 0x0000003f }, \ + { 0x9940, 0x00000004 }, \ + { 0x9948, 0x00000000 }, \ + { 0x994c, 0x00000000 }, \ + { 0x9950, 0x00000000 }, \ + { 0x9954, 0x5d50f14c }, \ + { 0x9958, 0x00000018 }, \ + { 0x995c, 0x004b6a8e }, \ + { 0xa184, 0x06ff05ff }, \ + { 0xa188, 0x07ff07ff }, \ + { 0xa18c, 0x08ff08ff }, \ + { 0xa190, 0x09ff09ff }, \ + { 0xa194, 0x0aff0aff }, \ + { 0xa198, 0x0bff0bff }, \ + { 0xa19c, 0x0cff0cff }, \ + { 0xa1a0, 0x0dff0dff }, \ + { 0xa1a4, 0x0fff0eff }, \ + { 0xa1a8, 0x12ff12ff }, \ + { 0xa1ac, 0x14ff13ff }, \ + { 0xa1b0, 0x16ff15ff }, \ + { 0xa1b4, 0x19ff17ff }, \ + { 0xa1b8, 0x1bff1aff }, \ + { 0xa1bc, 0x1eff1dff }, \ + { 0xa1c0, 0x23ff20ff }, \ + { 0xa1c4, 0x27ff25ff }, \ + { 0xa1c8, 0x2cff29ff }, \ + { 0xa1cc, 0x31ff2fff }, \ + { 0xa1d0, 0x37ff34ff }, \ + { 0xa1d4, 0x3aff3aff }, \ + { 0xa1d8, 0x3aff3aff }, \ + { 0xa1dc, 0x3aff3aff }, \ + { 0xa1e0, 0x3aff3aff }, \ + { 0xa1e4, 0x3aff3aff }, \ + { 0xa1e8, 0x3aff3aff }, \ + { 0xa1ec, 0x3aff3aff }, \ + { 0xa1f0, 0x3aff3aff }, \ + { 0xa1f4, 0x3aff3aff }, \ + { 0xa1f8, 0x3aff3aff }, \ + { 0xa1fc, 0x3aff3aff }, \ + /* BB gain table (64bytes) */ \ + { 0x9b00, 0x00000000 }, \ + { 0x9b04, 0x00000020 }, \ + { 0x9b08, 0x00000010 }, \ + { 0x9b0c, 0x00000030 }, \ + { 0x9b10, 0x00000008 }, \ + { 0x9b14, 0x00000028 }, \ + { 0x9b18, 0x00000004 }, \ + { 0x9b1c, 0x00000024 }, \ + { 0x9b20, 0x00000014 }, \ + { 0x9b24, 0x00000034 }, \ + { 0x9b28, 0x0000000c }, \ + { 0x9b2c, 0x0000002c }, \ + { 0x9b30, 0x00000002 }, \ + { 0x9b34, 0x00000022 }, \ + { 0x9b38, 0x00000012 }, \ + { 0x9b3c, 0x00000032 }, \ + { 0x9b40, 0x0000000a }, \ + { 0x9b44, 0x0000002a }, \ + { 0x9b48, 0x00000006 }, \ + { 0x9b4c, 0x00000026 }, \ + { 0x9b50, 0x00000016 }, \ + { 0x9b54, 0x00000036 }, \ + { 0x9b58, 0x0000000e }, \ + { 0x9b5c, 0x0000002e }, \ + { 0x9b60, 0x00000001 }, \ + { 0x9b64, 0x00000021 }, \ + { 0x9b68, 0x00000011 }, \ + { 0x9b6c, 0x00000031 }, \ + { 0x9b70, 0x00000009 }, \ + { 0x9b74, 0x00000029 }, \ + { 0x9b78, 0x00000005 }, \ + { 0x9b7c, 0x00000025 }, \ + { 0x9b80, 0x00000015 }, \ + { 0x9b84, 0x00000035 }, \ + { 0x9b88, 0x0000000d }, \ + { 0x9b8c, 0x0000002d }, \ + { 0x9b90, 0x00000003 }, \ + { 0x9b94, 0x00000023 }, \ + { 0x9b98, 0x00000013 }, \ + { 0x9b9c, 0x00000033 }, \ + { 0x9ba0, 0x0000000b }, \ + { 0x9ba4, 0x0000002b }, \ + { 0x9ba8, 0x0000002b }, \ + { 0x9bac, 0x0000002b }, \ + { 0x9bb0, 0x0000002b }, \ + { 0x9bb4, 0x0000002b }, \ + { 0x9bb8, 0x0000002b }, \ + { 0x9bbc, 0x0000002b }, \ + { 0x9bc0, 0x0000002b }, \ + { 0x9bc4, 0x0000002b }, \ + { 0x9bc8, 0x0000002b }, \ + { 0x9bcc, 0x0000002b }, \ + { 0x9bd0, 0x0000002b }, \ + { 0x9bd4, 0x0000002b }, \ + { 0x9bd8, 0x0000002b }, \ + { 0x9bdc, 0x0000002b }, \ + { 0x9be0, 0x0000002b }, \ + { 0x9be4, 0x0000002b }, \ + { 0x9be8, 0x0000002b }, \ + { 0x9bec, 0x0000002b }, \ + { 0x9bf0, 0x0000002b }, \ + { 0x9bf4, 0x0000002b }, \ + { 0x9bf8, 0x00000002 }, \ + { 0x9bfc, 0x00000016 }, \ + /* PHY activation */ \ + { 0x98d4, 0x00000020 }, \ + { 0x98d8, 0x00601068 }, \ +} + +struct ar5k_ar5211_ini_mode { + u_int16_t mode_register; + u_int32_t mode_value[4]; +}; + +#define AR5K_AR5211_INI_MODE { \ + { 0x0030, { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } }, \ + { 0x1040, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x1044, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x1048, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x104c, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x1050, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x1054, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x1058, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x105c, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x1060, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x1064, { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, \ + { 0x1070, { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } }, \ + { 0x1030, { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } }, \ + { 0x10b0, { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } }, \ + { 0x10f0, { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } }, \ + { 0x8014, { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } }, \ + { 0x801c, { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } }, \ + { 0x9804, { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } }, \ + { 0x9820, { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } }, \ + { 0x9824, { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } }, \ + { 0x9828, { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } }, \ + { 0x9834, { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, \ + { 0x9838, { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } }, \ + { 0x9844, { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } }, \ + { 0x9848, { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, \ + { 0x9850, { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, \ + { 0x9858, { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, \ + { 0x985c, { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, \ + { 0x9860, { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, \ + { 0x9864, { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, \ + { 0x9914, { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } }, \ + { 0x9918, { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } }, \ + { 0x9944, { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, \ + { 0xa180, { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, \ + { 0x98d4, { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } }, \ +} + +#endif /* _AR5K_AR5211_VAR_H */ diff --git a/sys/dev/ic/ar5212.c b/sys/dev/ic/ar5212.c index a12555ca234..e539b0de8e7 100644 --- a/sys/dev/ic/ar5212.c +++ b/sys/dev/ic/ar5212.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5212.c,v 1.2 2005/02/19 17:57:15 reyk Exp $ */ +/* $OpenBSD: ar5212.c,v 1.3 2005/02/25 22:25:30 reyk Exp $ */ /* * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> @@ -38,8 +38,6 @@ 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,); @@ -516,9 +514,8 @@ ar5k_ar5212_reset(hal, op_mode, channel, change_channel, status) * 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]); + if (ar5k_rfgain(hal, phy, freq) == AH_FALSE) + return (AH_FALSE); AR5K_DELAY(1000); diff --git a/sys/dev/ic/ar5212var.h b/sys/dev/ic/ar5212var.h index 2bbf18022af..22340f0f2c0 100644 --- a/sys/dev/ic/ar5212var.h +++ b/sys/dev/ic/ar5212var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5212var.h,v 1.1 2005/02/19 16:58:00 reyk Exp $ */ +/* $OpenBSD: ar5212var.h,v 1.2 2005/02/25 22:25:30 reyk Exp $ */ /* * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> @@ -30,7 +30,7 @@ * Define a "magic" code for the AR5212 (the HAL layer wants it) */ -#define AR5K_AR5212_MAGIC 0x0000145b /* 5212 */ +#define AR5K_AR5212_MAGIC 0x0000145c /* 5212 */ #define AR5K_AR5212_TX_NUM_QUEUES 10 #if BYTE_ORDER == BIG_ENDIAN @@ -600,10 +600,6 @@ 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 { \ @@ -773,143 +769,4 @@ struct ar5k_ar5212_ini_mode { } }, \ } -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 e89b50304e0..3d004e34fc6 100644 --- a/sys/dev/ic/ar5xxx.c +++ b/sys/dev/ic/ar5xxx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5xxx.c,v 1.14 2005/02/23 14:26:54 reyk Exp $ */ +/* $OpenBSD: ar5xxx.c,v 1.15 2005/02/25 22:25:30 reyk Exp $ */ /* * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> @@ -26,9 +26,7 @@ #include <dev/ic/ar5xxx.h> extern ar5k_attach_t ar5k_ar5210_attach; -#ifdef notyet extern ar5k_attach_t ar5k_ar5211_attach; -#endif extern ar5k_attach_t ar5k_ar5212_attach; static const struct @@ -51,7 +49,6 @@ static const struct { ar5k_ar5210_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_DEFAULT, ar5k_ar5210_attach }, -#ifdef notyet { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211, ar5k_ar5211_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_DEFAULT, @@ -62,7 +59,6 @@ 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, @@ -100,6 +96,8 @@ static const struct ar5k_ini_rf ar5111_rf[] = AR5K_AR5111_INI_RF; static const struct ar5k_ini_rf ar5112_rf[] = AR5K_AR5112_INI_RF; +static const struct ar5k_ini_rfgain ar5k_rfg[] = + AR5K_INI_RFGAIN; /* * Enable to overwrite the country code (use "00" for debug) @@ -1493,3 +1491,34 @@ ar5k_ar5112_rfregs(hal, channel, mode) return (AH_TRUE); } + +HAL_BOOL +ar5k_rfgain(hal, phy, freq) + struct ath_hal *hal; + u_int phy, freq; +{ + int i; + + switch (phy) { + case AR5K_INI_PHY_5111: + case AR5K_INI_PHY_5112: + break; + default: + return (AH_FALSE); + } + + switch (freq) { + case AR5K_INI_RFGAIN_2GHZ: + case AR5K_INI_RFGAIN_5GHZ: + break; + default: + return (AH_FALSE); + } + + for (i = 0; i < AR5K_ELEMENTS(ar5k_rfg); i++) { + AR5K_REG_WRITE((u_int32_t)ar5k_rfg[i].rfg_register, + ar5k_rfg[i].rfg_value[phy][freq]); + } + + return (AH_TRUE); +} diff --git a/sys/dev/ic/ar5xxx.h b/sys/dev/ic/ar5xxx.h index 433cc6abc65..967f8d2d73d 100644 --- a/sys/dev/ic/ar5xxx.h +++ b/sys/dev/ic/ar5xxx.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5xxx.h,v 1.11 2005/02/17 23:52:05 reyk Exp $ */ +/* $OpenBSD: ar5xxx.h,v 1.12 2005/02/25 22:25:30 reyk Exp $ */ /* * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> @@ -1275,6 +1275,10 @@ struct ar5k_ini { #define AR5K_INI_VAL_XR 0 #define AR5K_INI_VAL_MAX 5 +#define AR5K_INI_PHY_5111 0 +#define AR5K_INI_PHY_5112 1 +#define AR5K_INI_PHY_511X 1 + #define AR5K_AR5111_INI_RF_MAX_BANKS 8 #define AR5K_AR5112_INI_RF_MAX_BANKS 8 @@ -1377,7 +1381,7 @@ struct ar5k_ini_rf { { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } }, \ } -#define AR5K_AR5112_INI_RF { \ +#define AR5K_AR5112_INI_RF { \ { 1, 0x98d4, \ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, \ { 2, 0x98d0, \ @@ -1492,6 +1496,145 @@ struct ar5k_ini_rf { { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, \ } +struct ar5k_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_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 } } }, \ +} + /* * Prototypes */ @@ -1532,6 +1675,7 @@ HAL_BOOL ar5k_eeprom_regulation_domain(struct ath_hal *, HAL_BOOL ar5k_channel(struct ath_hal *, HAL_CHANNEL *); HAL_BOOL ar5k_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int); +HAL_BOOL ar5k_rfgain(struct ath_hal *, u_int, u_int); __END_DECLS |