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