Initial commit; kernel source import

This commit is contained in:
Nathan
2025-04-06 23:50:55 -05:00
commit 25c6d769f4
45093 changed files with 18199410 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
config CARL9170
tristate "Linux Community AR9170 802.11n USB support"
depends on USB && MAC80211 && EXPERIMENTAL
select ATH_COMMON
select FW_LOADER
select CRC32
help
This is another driver for the Atheros "otus" 802.11n USB devices.
This driver provides more features than the original,
but it needs a special firmware (carl9170-1.fw) to do that.
The firmware can be downloaded from our wiki here:
<http://wireless.kernel.org/en/users/Drivers/carl9170>
If you choose to build a module, it'll be called carl9170.
config CARL9170_LEDS
bool "SoftLED Support"
depends on CARL9170
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
default y
help
This option is necessary, if you want your device' LEDs to blink
Say Y, unless you need the LEDs for firmware debugging.
config CARL9170_DEBUGFS
bool "DebugFS Support"
depends on CARL9170 && DEBUG_FS && MAC80211_DEBUGFS
default n
help
Export several driver and device internals to user space.
Say N.
config CARL9170_WPC
bool
depends on CARL9170 && (INPUT = y || INPUT = CARL9170)
default y
config CARL9170_HWRNG
bool "Random number generator"
depends on CARL9170 && (HW_RANDOM = y || HW_RANDOM = CARL9170)
default n
help
Provides a hardware random number generator to the kernel.
SECURITY WARNING: It's relatively easy to eavesdrop all
generated random numbers from the transport stream with
usbmon [software] or special usb sniffer hardware.
Say N, unless your setup[i.e.: embedded system] has no
other rng source and you can afford to take the risk.

View File

@@ -0,0 +1,4 @@
carl9170-objs := main.o usb.o cmd.o mac.o phy.o led.o fw.o tx.o rx.o
carl9170-$(CONFIG_CARL9170_DEBUGFS) += debug.o
obj-$(CONFIG_CARL9170) += carl9170.o

View File

@@ -0,0 +1,677 @@
/*
* Atheros CARL9170 driver
*
* Driver specific definitions
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#ifndef __CARL9170_H
#define __CARL9170_H
#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
#include <linux/hw_random.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <linux/usb.h>
#ifdef CONFIG_CARL9170_LEDS
#include <linux/leds.h>
#endif /* CONFIG_CARL9170_LEDS */
#ifdef CONFIG_CARL9170_WPC
#include <linux/input.h>
#endif /* CONFIG_CARL9170_WPC */
#include "eeprom.h"
#include "wlan.h"
#include "hw.h"
#include "fwdesc.h"
#include "fwcmd.h"
#include "../regd.h"
#ifdef CONFIG_CARL9170_DEBUGFS
#include "debug.h"
#endif /* CONFIG_CARL9170_DEBUGFS */
#define CARL9170FW_NAME "carl9170-1.fw"
#define PAYLOAD_MAX (CARL9170_MAX_CMD_LEN / 4 - 1)
static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
enum carl9170_rf_init_mode {
CARL9170_RFI_NONE,
CARL9170_RFI_WARM,
CARL9170_RFI_COLD,
};
#define CARL9170_MAX_RX_BUFFER_SIZE 8192
enum carl9170_device_state {
CARL9170_UNKNOWN_STATE,
CARL9170_STOPPED,
CARL9170_IDLE,
CARL9170_STARTED,
};
#define CARL9170_NUM_TID 16
#define WME_BA_BMP_SIZE 64
#define CARL9170_TX_USER_RATE_TRIES 3
#define WME_AC_BE 2
#define WME_AC_BK 3
#define WME_AC_VI 1
#define WME_AC_VO 0
#define TID_TO_WME_AC(_tid) \
((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
(((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
(((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
WME_AC_VO)
#define SEQ_DIFF(_start, _seq) \
(((_start) - (_seq)) & 0x0fff)
#define SEQ_PREV(_seq) \
(((_seq) - 1) & 0x0fff)
#define SEQ_NEXT(_seq) \
(((_seq) + 1) & 0x0fff)
#define BAW_WITHIN(_start, _bawsz, _seqno) \
((((_seqno) - (_start)) & 0xfff) < (_bawsz))
enum carl9170_tid_state {
CARL9170_TID_STATE_INVALID,
CARL9170_TID_STATE_KILLED,
CARL9170_TID_STATE_SHUTDOWN,
CARL9170_TID_STATE_SUSPEND,
CARL9170_TID_STATE_PROGRESS,
CARL9170_TID_STATE_IDLE,
CARL9170_TID_STATE_XMIT,
};
#define CARL9170_BAW_BITS (2 * WME_BA_BMP_SIZE)
#define CARL9170_BAW_SIZE (BITS_TO_LONGS(CARL9170_BAW_BITS))
#define CARL9170_BAW_LEN (DIV_ROUND_UP(CARL9170_BAW_BITS, BITS_PER_BYTE))
struct carl9170_sta_tid {
/* must be the first entry! */
struct list_head list;
/* temporary list for RCU unlink procedure */
struct list_head tmp_list;
/* lock for the following data structures */
spinlock_t lock;
unsigned int counter;
enum carl9170_tid_state state;
u8 tid; /* TID number ( 0 - 15 ) */
u16 max; /* max. AMPDU size */
u16 snx; /* awaiting _next_ frame */
u16 hsn; /* highest _queued_ sequence */
u16 bsn; /* base of the tx/agg bitmap */
unsigned long bitmap[CARL9170_BAW_SIZE];
/* Preaggregation reorder queue */
struct sk_buff_head queue;
};
#define CARL9170_QUEUE_TIMEOUT 256
#define CARL9170_BUMP_QUEUE 1000
#define CARL9170_TX_TIMEOUT 2500
#define CARL9170_JANITOR_DELAY 128
#define CARL9170_QUEUE_STUCK_TIMEOUT 5500
#define CARL9170_STAT_WORK 30000
#define CARL9170_NUM_TX_AGG_MAX 30
/*
* Tradeoff between stability/latency and speed.
*
* AR9170_TXQ_DEPTH is devised by dividing the amount of available
* tx buffers with the size of a full ethernet frame + overhead.
*
* Naturally: The higher the limit, the faster the device CAN send.
* However, even a slight over-commitment at the wrong time and the
* hardware is doomed to send all already-queued frames at suboptimal
* rates. This in turn leads to an enormous amount of unsuccessful
* retries => Latency goes up, whereas the throughput goes down. CRASH!
*/
#define CARL9170_NUM_TX_LIMIT_HARD ((AR9170_TXQ_DEPTH * 3) / 2)
#define CARL9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH)
struct carl9170_tx_queue_stats {
unsigned int count;
unsigned int limit;
unsigned int len;
};
struct carl9170_vif {
unsigned int id;
struct ieee80211_vif __rcu *vif;
};
struct carl9170_vif_info {
struct list_head list;
bool active;
unsigned int id;
struct sk_buff *beacon;
bool enable_beacon;
};
#define AR9170_NUM_RX_URBS 16
#define AR9170_NUM_RX_URBS_MUL 2
#define AR9170_NUM_TX_URBS 8
#define AR9170_NUM_RX_URBS_POOL (AR9170_NUM_RX_URBS_MUL * AR9170_NUM_RX_URBS)
enum carl9170_device_features {
CARL9170_WPS_BUTTON = BIT(0),
CARL9170_ONE_LED = BIT(1),
};
#ifdef CONFIG_CARL9170_LEDS
struct ar9170;
struct carl9170_led {
struct ar9170 *ar;
struct led_classdev l;
char name[32];
unsigned int toggled;
bool last_state;
bool registered;
};
#endif /* CONFIG_CARL9170_LEDS */
enum carl9170_restart_reasons {
CARL9170_RR_NO_REASON = 0,
CARL9170_RR_FATAL_FIRMWARE_ERROR,
CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
CARL9170_RR_WATCHDOG,
CARL9170_RR_STUCK_TX,
CARL9170_RR_UNRESPONSIVE_DEVICE,
CARL9170_RR_COMMAND_TIMEOUT,
CARL9170_RR_TOO_MANY_PHY_ERRORS,
CARL9170_RR_LOST_RSP,
CARL9170_RR_INVALID_RSP,
CARL9170_RR_USER_REQUEST,
__CARL9170_RR_LAST,
};
enum carl9170_erp_modes {
CARL9170_ERP_INVALID,
CARL9170_ERP_AUTO,
CARL9170_ERP_MAC80211,
CARL9170_ERP_OFF,
CARL9170_ERP_CTS,
CARL9170_ERP_RTS,
__CARL9170_ERP_NUM,
};
struct ar9170 {
struct ath_common common;
struct ieee80211_hw *hw;
struct mutex mutex;
enum carl9170_device_state state;
spinlock_t state_lock;
enum carl9170_restart_reasons last_reason;
bool registered;
/* USB */
struct usb_device *udev;
struct usb_interface *intf;
struct usb_anchor rx_anch;
struct usb_anchor rx_work;
struct usb_anchor rx_pool;
struct usb_anchor tx_wait;
struct usb_anchor tx_anch;
struct usb_anchor tx_cmd;
struct usb_anchor tx_err;
struct tasklet_struct usb_tasklet;
atomic_t tx_cmd_urbs;
atomic_t tx_anch_urbs;
atomic_t rx_anch_urbs;
atomic_t rx_work_urbs;
atomic_t rx_pool_urbs;
kernel_ulong_t features;
/* firmware settings */
struct completion fw_load_wait;
struct completion fw_boot_wait;
struct {
const struct carl9170fw_desc_head *desc;
const struct firmware *fw;
unsigned int offset;
unsigned int address;
unsigned int cmd_bufs;
unsigned int api_version;
unsigned int vif_num;
unsigned int err_counter;
unsigned int bug_counter;
u32 beacon_addr;
unsigned int beacon_max_len;
bool rx_stream;
bool tx_stream;
bool rx_filter;
bool hw_counters;
unsigned int mem_blocks;
unsigned int mem_block_size;
unsigned int rx_size;
unsigned int tx_seq_table;
bool ba_filter;
} fw;
/* interface configuration combinations */
struct ieee80211_iface_limit if_comb_limits[1];
struct ieee80211_iface_combination if_combs[1];
/* reset / stuck frames/queue detection */
struct work_struct restart_work;
struct work_struct ping_work;
unsigned int restart_counter;
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
bool needs_full_reset;
bool force_usb_reset;
atomic_t pending_restarts;
/* interface mode settings */
struct list_head vif_list;
unsigned long vif_bitmap;
unsigned int vifs;
struct carl9170_vif vif_priv[AR9170_MAX_VIRTUAL_MAC];
/* beaconing */
spinlock_t beacon_lock;
unsigned int global_pretbtt;
unsigned int global_beacon_int;
struct carl9170_vif_info __rcu *beacon_iter;
unsigned int beacon_enabled;
/* cryptographic engine */
u64 usedkeys;
bool rx_software_decryption;
bool disable_offload;
/* filter settings */
u64 cur_mc_hash;
u32 cur_filter;
unsigned int filter_state;
unsigned int rx_filter_caps;
bool sniffer_enabled;
/* MAC */
enum carl9170_erp_modes erp_mode;
/* PHY */
struct ieee80211_channel *channel;
unsigned int num_channels;
int noise[4];
unsigned int chan_fail;
unsigned int total_chan_fail;
u8 heavy_clip;
u8 ht_settings;
struct {
u64 active; /* usec */
u64 cca; /* usec */
u64 tx_time; /* usec */
u64 rx_total;
u64 rx_overrun;
} tally;
struct delayed_work stat_work;
struct survey_info *survey;
/* power calibration data */
u8 power_5G_leg[4];
u8 power_2G_cck[4];
u8 power_2G_ofdm[4];
u8 power_5G_ht20[8];
u8 power_5G_ht40[8];
u8 power_2G_ht20[8];
u8 power_2G_ht40[8];
#ifdef CONFIG_CARL9170_LEDS
/* LED */
struct delayed_work led_work;
struct carl9170_led leds[AR9170_NUM_LEDS];
#endif /* CONFIG_CARL9170_LEDS */
/* qos queue settings */
spinlock_t tx_stats_lock;
struct carl9170_tx_queue_stats tx_stats[__AR9170_NUM_TXQ];
struct ieee80211_tx_queue_params edcf[5];
struct completion tx_flush;
/* CMD */
int cmd_seq;
int readlen;
u8 *readbuf;
spinlock_t cmd_lock;
struct completion cmd_wait;
union {
__le32 cmd_buf[PAYLOAD_MAX + 1];
struct carl9170_cmd cmd;
struct carl9170_rsp rsp;
};
/* statistics */
unsigned int tx_dropped;
unsigned int tx_ack_failures;
unsigned int tx_fcs_errors;
unsigned int rx_dropped;
/* EEPROM */
struct ar9170_eeprom eeprom;
/* tx queuing */
struct sk_buff_head tx_pending[__AR9170_NUM_TXQ];
struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
struct delayed_work tx_janitor;
unsigned long tx_janitor_last_run;
bool tx_schedule;
/* tx ampdu */
struct work_struct ampdu_work;
spinlock_t tx_ampdu_list_lock;
struct carl9170_sta_tid __rcu *tx_ampdu_iter;
struct list_head tx_ampdu_list;
atomic_t tx_ampdu_upload;
atomic_t tx_ampdu_scheduler;
atomic_t tx_total_pending;
atomic_t tx_total_queued;
unsigned int tx_ampdu_list_len;
int current_density;
int current_factor;
bool tx_ampdu_schedule;
/* internal memory management */
spinlock_t mem_lock;
unsigned long *mem_bitmap;
atomic_t mem_free_blocks;
atomic_t mem_allocs;
/* rxstream mpdu merge */
struct ar9170_rx_head rx_plcp;
bool rx_has_plcp;
struct sk_buff *rx_failover;
int rx_failover_missing;
u32 ampdu_ref;
/* FIFO for collecting outstanding BlockAckRequest */
struct list_head bar_list[__AR9170_NUM_TXQ];
spinlock_t bar_list_lock[__AR9170_NUM_TXQ];
#ifdef CONFIG_CARL9170_WPC
struct {
bool pbc_state;
struct input_dev *pbc;
char name[32];
char phys[32];
} wps;
#endif /* CONFIG_CARL9170_WPC */
#ifdef CONFIG_CARL9170_DEBUGFS
struct carl9170_debug debug;
struct dentry *debug_dir;
#endif /* CONFIG_CARL9170_DEBUGFS */
/* PSM */
struct work_struct ps_work;
struct {
unsigned int dtim_counter;
unsigned long last_beacon;
unsigned long last_action;
unsigned long last_slept;
unsigned int sleep_ms;
unsigned int off_override;
bool state;
} ps;
#ifdef CONFIG_CARL9170_HWRNG
# define CARL9170_HWRNG_CACHE_SIZE CARL9170_MAX_CMD_PAYLOAD_LEN
struct {
struct hwrng rng;
bool initialized;
char name[30 + 1];
u16 cache[CARL9170_HWRNG_CACHE_SIZE / sizeof(u16)];
unsigned int cache_idx;
} rng;
#endif /* CONFIG_CARL9170_HWRNG */
};
enum carl9170_ps_off_override_reasons {
PS_OFF_VIF = BIT(0),
PS_OFF_BCN = BIT(1),
};
struct carl9170_bar_list_entry {
struct list_head list;
struct rcu_head head;
struct sk_buff *skb;
};
struct carl9170_ba_stats {
u8 ampdu_len;
u8 ampdu_ack_len;
bool clear;
bool req;
};
struct carl9170_sta_info {
bool ht_sta;
bool sleeping;
atomic_t pending_frames;
unsigned int ampdu_max_len;
struct carl9170_sta_tid __rcu *agg[CARL9170_NUM_TID];
struct carl9170_ba_stats stats[CARL9170_NUM_TID];
};
struct carl9170_tx_info {
unsigned long timeout;
struct ar9170 *ar;
struct kref ref;
};
#define CHK_DEV_STATE(a, s) (((struct ar9170 *)a)->state >= (s))
#define IS_INITIALIZED(a) (CHK_DEV_STATE(a, CARL9170_STOPPED))
#define IS_ACCEPTING_CMD(a) (CHK_DEV_STATE(a, CARL9170_IDLE))
#define IS_STARTED(a) (CHK_DEV_STATE(a, CARL9170_STARTED))
static inline void __carl9170_set_state(struct ar9170 *ar,
enum carl9170_device_state newstate)
{
ar->state = newstate;
}
static inline void carl9170_set_state(struct ar9170 *ar,
enum carl9170_device_state newstate)
{
unsigned long flags;
spin_lock_irqsave(&ar->state_lock, flags);
__carl9170_set_state(ar, newstate);
spin_unlock_irqrestore(&ar->state_lock, flags);
}
static inline void carl9170_set_state_when(struct ar9170 *ar,
enum carl9170_device_state min, enum carl9170_device_state newstate)
{
unsigned long flags;
spin_lock_irqsave(&ar->state_lock, flags);
if (CHK_DEV_STATE(ar, min))
__carl9170_set_state(ar, newstate);
spin_unlock_irqrestore(&ar->state_lock, flags);
}
/* exported interface */
void *carl9170_alloc(size_t priv_size);
int carl9170_register(struct ar9170 *ar);
void carl9170_unregister(struct ar9170 *ar);
void carl9170_free(struct ar9170 *ar);
void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r);
void carl9170_ps_check(struct ar9170 *ar);
/* USB back-end */
int carl9170_usb_open(struct ar9170 *ar);
void carl9170_usb_stop(struct ar9170 *ar);
void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb);
void carl9170_usb_handle_tx_err(struct ar9170 *ar);
int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids,
u32 plen, void *payload, u32 rlen, void *resp);
int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
const bool free_buf);
int carl9170_usb_restart(struct ar9170 *ar);
void carl9170_usb_reset(struct ar9170 *ar);
/* MAC */
int carl9170_init_mac(struct ar9170 *ar);
int carl9170_set_qos(struct ar9170 *ar);
int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hast);
int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id,
const u8 *mac);
int carl9170_set_operating_mode(struct ar9170 *ar);
int carl9170_set_beacon_timers(struct ar9170 *ar);
int carl9170_set_dyn_sifs_ack(struct ar9170 *ar);
int carl9170_set_rts_cts_rate(struct ar9170 *ar);
int carl9170_set_ampdu_settings(struct ar9170 *ar);
int carl9170_set_slot_time(struct ar9170 *ar);
int carl9170_set_mac_rates(struct ar9170 *ar);
int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry);
int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen);
int carl9170_disable_key(struct ar9170 *ar, const u8 id);
int carl9170_set_mac_tpc(struct ar9170 *ar, struct ieee80211_channel *channel);
/* RX */
void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len);
void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
/* TX */
void carl9170_op_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb);
void carl9170_tx_janitor(struct work_struct *work);
void carl9170_tx_process_status(struct ar9170 *ar,
const struct carl9170_rsp *cmd);
void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
const bool success);
void carl9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb);
void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb);
void carl9170_tx_scheduler(struct ar9170 *ar);
void carl9170_tx_get_skb(struct sk_buff *skb);
int carl9170_tx_put_skb(struct sk_buff *skb);
int carl9170_update_beacon(struct ar9170 *ar, const bool submit);
/* LEDs */
#ifdef CONFIG_CARL9170_LEDS
int carl9170_led_register(struct ar9170 *ar);
void carl9170_led_unregister(struct ar9170 *ar);
#endif /* CONFIG_CARL9170_LEDS */
int carl9170_led_init(struct ar9170 *ar);
int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state);
/* PHY / RF */
int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi);
int carl9170_get_noisefloor(struct ar9170 *ar);
/* FW */
int carl9170_parse_firmware(struct ar9170 *ar);
extern struct ieee80211_rate __carl9170_ratetable[];
extern int modparam_noht;
static inline struct ar9170 *carl9170_get_priv(struct carl9170_vif *carl_vif)
{
return container_of(carl_vif, struct ar9170,
vif_priv[carl_vif->id]);
}
static inline struct ieee80211_hdr *carl9170_get_hdr(struct sk_buff *skb)
{
return (void *)((struct _carl9170_tx_superframe *)
skb->data)->frame_data;
}
static inline u16 get_seq_h(struct ieee80211_hdr *hdr)
{
return le16_to_cpu(hdr->seq_ctrl) >> 4;
}
static inline u16 carl9170_get_seq(struct sk_buff *skb)
{
return get_seq_h(carl9170_get_hdr(skb));
}
static inline u16 get_tid_h(struct ieee80211_hdr *hdr)
{
return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
}
static inline u16 carl9170_get_tid(struct sk_buff *skb)
{
return get_tid_h(carl9170_get_hdr(skb));
}
static inline struct ieee80211_vif *
carl9170_get_vif(struct carl9170_vif_info *priv)
{
return container_of((void *)priv, struct ieee80211_vif, drv_priv);
}
/* Protected by ar->mutex or RCU */
static inline struct ieee80211_vif *carl9170_get_main_vif(struct ar9170 *ar)
{
struct carl9170_vif_info *cvif;
list_for_each_entry_rcu(cvif, &ar->vif_list, list) {
if (cvif->active)
return carl9170_get_vif(cvif);
}
return NULL;
}
static inline bool is_main_vif(struct ar9170 *ar, struct ieee80211_vif *vif)
{
bool ret;
rcu_read_lock();
ret = (carl9170_get_main_vif(ar) == vif);
rcu_read_unlock();
return ret;
}
#endif /* __CARL9170_H */

View File

@@ -0,0 +1,222 @@
/*
* Atheros CARL9170 driver
*
* Basic HW register/memory/command access functions
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#include <asm/div64.h>
#include "carl9170.h"
#include "cmd.h"
int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
{
const __le32 buf[2] = {
cpu_to_le32(reg),
cpu_to_le32(val),
};
int err;
err = carl9170_exec_cmd(ar, CARL9170_CMD_WREG, sizeof(buf),
(u8 *) buf, 0, NULL);
if (err) {
if (net_ratelimit()) {
wiphy_err(ar->hw->wiphy, "writing reg %#x "
"(val %#x) failed (%d)\n", reg, val, err);
}
}
return err;
}
int carl9170_read_mreg(struct ar9170 *ar, const int nregs,
const u32 *regs, u32 *out)
{
int i, err;
__le32 *offs, *res;
/* abuse "out" for the register offsets, must be same length */
offs = (__le32 *)out;
for (i = 0; i < nregs; i++)
offs[i] = cpu_to_le32(regs[i]);
/* also use the same buffer for the input */
res = (__le32 *)out;
err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
4 * nregs, (u8 *)offs,
4 * nregs, (u8 *)res);
if (err) {
if (net_ratelimit()) {
wiphy_err(ar->hw->wiphy, "reading regs failed (%d)\n",
err);
}
return err;
}
/* convert result to cpu endian */
for (i = 0; i < nregs; i++)
out[i] = le32_to_cpu(res[i]);
return 0;
}
int carl9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val)
{
return carl9170_read_mreg(ar, 1, &reg, val);
}
int carl9170_echo_test(struct ar9170 *ar, const u32 v)
{
u32 echores;
int err;
err = carl9170_exec_cmd(ar, CARL9170_CMD_ECHO,
4, (u8 *)&v,
4, (u8 *)&echores);
if (err)
return err;
if (v != echores) {
wiphy_info(ar->hw->wiphy, "wrong echo %x != %x", v, echores);
return -EINVAL;
}
return 0;
}
struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
const enum carl9170_cmd_oids cmd, const unsigned int len)
{
struct carl9170_cmd *tmp;
tmp = kzalloc(sizeof(struct carl9170_cmd_head) + len, GFP_ATOMIC);
if (tmp) {
tmp->hdr.cmd = cmd;
tmp->hdr.len = len;
}
return tmp;
}
int carl9170_reboot(struct ar9170 *ar)
{
struct carl9170_cmd *cmd;
int err;
cmd = carl9170_cmd_buf(ar, CARL9170_CMD_REBOOT_ASYNC, 0);
if (!cmd)
return -ENOMEM;
err = __carl9170_exec_cmd(ar, cmd, true);
return err;
}
int carl9170_mac_reset(struct ar9170 *ar)
{
return carl9170_exec_cmd(ar, CARL9170_CMD_SWRST,
0, NULL, 0, NULL);
}
int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
const u32 mode, const u32 addr, const u32 len)
{
struct carl9170_cmd *cmd;
cmd = carl9170_cmd_buf(ar, CARL9170_CMD_BCN_CTRL_ASYNC,
sizeof(struct carl9170_bcn_ctrl_cmd));
if (!cmd)
return -ENOMEM;
cmd->bcn_ctrl.vif_id = cpu_to_le32(vif_id);
cmd->bcn_ctrl.mode = cpu_to_le32(mode);
cmd->bcn_ctrl.bcn_addr = cpu_to_le32(addr);
cmd->bcn_ctrl.bcn_len = cpu_to_le32(len);
return __carl9170_exec_cmd(ar, cmd, true);
}
int carl9170_collect_tally(struct ar9170 *ar)
{
struct carl9170_tally_rsp tally;
struct survey_info *info;
unsigned int tick;
int err;
err = carl9170_exec_cmd(ar, CARL9170_CMD_TALLY, 0, NULL,
sizeof(tally), (u8 *)&tally);
if (err)
return err;
tick = le32_to_cpu(tally.tick);
if (tick) {
ar->tally.active += le32_to_cpu(tally.active) / tick;
ar->tally.cca += le32_to_cpu(tally.cca) / tick;
ar->tally.tx_time += le32_to_cpu(tally.tx_time) / tick;
ar->tally.rx_total += le32_to_cpu(tally.rx_total);
ar->tally.rx_overrun += le32_to_cpu(tally.rx_overrun);
if (ar->channel) {
info = &ar->survey[ar->channel->hw_value];
info->channel_time = ar->tally.active;
info->channel_time_busy = ar->tally.cca;
info->channel_time_tx = ar->tally.tx_time;
do_div(info->channel_time, 1000);
do_div(info->channel_time_busy, 1000);
do_div(info->channel_time_tx, 1000);
}
}
return 0;
}
int carl9170_powersave(struct ar9170 *ar, const bool ps)
{
struct carl9170_cmd *cmd;
u32 state;
cmd = carl9170_cmd_buf(ar, CARL9170_CMD_PSM_ASYNC,
sizeof(struct carl9170_psm));
if (!cmd)
return -ENOMEM;
if (ps) {
/* Sleep until next TBTT */
state = CARL9170_PSM_SLEEP | 1;
} else {
/* wake up immediately */
state = 1;
}
cmd->psm.state = cpu_to_le32(state);
return __carl9170_exec_cmd(ar, cmd, true);
}

View File

@@ -0,0 +1,174 @@
/*
* Atheros CARL9170 driver
*
* Basic HW register/memory/command access functions
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2010, Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#ifndef __CMD_H
#define __CMD_H
#include "carl9170.h"
/* basic HW access */
int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
int carl9170_read_reg(struct ar9170 *ar, const u32 reg, u32 *val);
int carl9170_read_mreg(struct ar9170 *ar, const int nregs,
const u32 *regs, u32 *out);
int carl9170_echo_test(struct ar9170 *ar, u32 v);
int carl9170_reboot(struct ar9170 *ar);
int carl9170_mac_reset(struct ar9170 *ar);
int carl9170_powersave(struct ar9170 *ar, const bool power_on);
int carl9170_collect_tally(struct ar9170 *ar);
int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
const u32 mode, const u32 addr, const u32 len);
static inline int carl9170_flush_cab(struct ar9170 *ar,
const unsigned int vif_id)
{
return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0);
}
static inline int carl9170_rx_filter(struct ar9170 *ar,
const unsigned int _rx_filter)
{
__le32 rx_filter = cpu_to_le32(_rx_filter);
return carl9170_exec_cmd(ar, CARL9170_CMD_RX_FILTER,
sizeof(rx_filter), (u8 *)&rx_filter,
0, NULL);
}
struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
const enum carl9170_cmd_oids cmd, const unsigned int len);
/*
* Macros to facilitate writing multiple registers in a single
* write-combining USB command. Note that when the first group
* fails the whole thing will fail without any others attempted,
* but you won't know which write in the group failed.
*/
#define carl9170_regwrite_begin(ar) \
do { \
int __nreg = 0, __err = 0; \
struct ar9170 *__ar = ar;
#define carl9170_regwrite(r, v) do { \
__ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r); \
__ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v); \
__nreg++; \
if ((__nreg >= PAYLOAD_MAX / 2)) { \
if (IS_ACCEPTING_CMD(__ar)) \
__err = carl9170_exec_cmd(__ar, \
CARL9170_CMD_WREG, 8 * __nreg, \
(u8 *) &__ar->cmd_buf[1], 0, NULL); \
else \
goto __regwrite_out; \
\
__nreg = 0; \
if (__err) \
goto __regwrite_out; \
} \
} while (0)
#define carl9170_regwrite_finish() \
__regwrite_out : \
if (__err == 0 && __nreg) { \
if (IS_ACCEPTING_CMD(__ar)) \
__err = carl9170_exec_cmd(__ar, \
CARL9170_CMD_WREG, 8 * __nreg, \
(u8 *) &__ar->cmd_buf[1], 0, NULL); \
__nreg = 0; \
}
#define carl9170_regwrite_result() \
__err; \
} while (0)
#define carl9170_async_regwrite_get_buf() \
do { \
__nreg = 0; \
__cmd = carl9170_cmd_buf(__carl, CARL9170_CMD_WREG_ASYNC, \
CARL9170_MAX_CMD_PAYLOAD_LEN); \
if (__cmd == NULL) { \
__err = -ENOMEM; \
goto __async_regwrite_out; \
} \
} while (0)
#define carl9170_async_regwrite_begin(carl) \
do { \
struct ar9170 *__carl = carl; \
struct carl9170_cmd *__cmd; \
unsigned int __nreg; \
int __err = 0; \
carl9170_async_regwrite_get_buf(); \
#define carl9170_async_regwrite_flush() \
do { \
if (__cmd == NULL || __nreg == 0) \
break; \
\
if (IS_ACCEPTING_CMD(__carl) && __nreg) { \
__cmd->hdr.len = 8 * __nreg; \
__err = __carl9170_exec_cmd(__carl, __cmd, true); \
__cmd = NULL; \
break; \
} \
goto __async_regwrite_out; \
} while (0)
#define carl9170_async_regwrite(r, v) do { \
if (__cmd == NULL) \
carl9170_async_regwrite_get_buf(); \
__cmd->wreg.regs[__nreg].addr = cpu_to_le32(r); \
__cmd->wreg.regs[__nreg].val = cpu_to_le32(v); \
__nreg++; \
if ((__nreg >= PAYLOAD_MAX / 2)) \
carl9170_async_regwrite_flush(); \
} while (0)
#define carl9170_async_regwrite_finish() do { \
__async_regwrite_out: \
if (__cmd != NULL && __err == 0) \
carl9170_async_regwrite_flush(); \
kfree(__cmd); \
} while (0) \
#define carl9170_async_regwrite_result() \
__err; \
} while (0)
#endif /* __CMD_H */

View File

@@ -0,0 +1,897 @@
/*
* Atheros CARL9170 driver
*
* debug(fs) probing
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2008-2009 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/vmalloc.h>
#include "carl9170.h"
#include "cmd.h"
#define ADD(buf, off, max, fmt, args...) \
off += snprintf(&buf[off], max - off, fmt, ##args);
struct carl9170_debugfs_fops {
unsigned int read_bufsize;
umode_t attr;
char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize,
ssize_t *len);
ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size);
const struct file_operations fops;
enum carl9170_device_state req_dev_state;
};
static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct carl9170_debugfs_fops *dfops;
struct ar9170 *ar;
char *buf = NULL, *res_buf = NULL;
ssize_t ret = 0;
int err = 0;
if (!count)
return 0;
ar = file->private_data;
if (!ar)
return -ENODEV;
dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops);
if (!dfops->read)
return -ENOSYS;
if (dfops->read_bufsize) {
buf = vmalloc(dfops->read_bufsize);
if (!buf)
return -ENOMEM;
}
mutex_lock(&ar->mutex);
if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
err = -ENODEV;
res_buf = buf;
goto out_free;
}
res_buf = dfops->read(ar, buf, dfops->read_bufsize, &ret);
if (ret > 0)
err = simple_read_from_buffer(userbuf, count, ppos,
res_buf, ret);
else
err = ret;
WARN_ON_ONCE(dfops->read_bufsize && (res_buf != buf));
out_free:
vfree(res_buf);
mutex_unlock(&ar->mutex);
return err;
}
static ssize_t carl9170_debugfs_write(struct file *file,
const char __user *userbuf, size_t count, loff_t *ppos)
{
struct carl9170_debugfs_fops *dfops;
struct ar9170 *ar;
char *buf = NULL;
int err = 0;
if (!count)
return 0;
if (count > PAGE_SIZE)
return -E2BIG;
ar = file->private_data;
if (!ar)
return -ENODEV;
dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops);
if (!dfops->write)
return -ENOSYS;
buf = vmalloc(count);
if (!buf)
return -ENOMEM;
if (copy_from_user(buf, userbuf, count)) {
err = -EFAULT;
goto out_free;
}
if (mutex_trylock(&ar->mutex) == 0) {
err = -EAGAIN;
goto out_free;
}
if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
err = -ENODEV;
goto out_unlock;
}
err = dfops->write(ar, buf, count);
if (err)
goto out_unlock;
out_unlock:
mutex_unlock(&ar->mutex);
out_free:
vfree(buf);
return err;
}
#define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \
_attr, _dstate) \
static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
.read_bufsize = _read_bufsize, \
.read = _read, \
.write = _write, \
.attr = _attr, \
.req_dev_state = _dstate, \
.fops = { \
.open = simple_open, \
.read = carl9170_debugfs_read, \
.write = carl9170_debugfs_write, \
.owner = THIS_MODULE \
}, \
}
#define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr) \
__DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \
_attr, CARL9170_STARTED) \
#define DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize) \
DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \
NULL, _read_bufsize, S_IRUSR)
#define DEBUGFS_DECLARE_WO_FILE(name) \
DEBUGFS_DECLARE_FILE(name, NULL, carl9170_debugfs_##name ##_write,\
0, S_IWUSR)
#define DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize) \
DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \
carl9170_debugfs_##name ##_write, \
_read_bufsize, S_IRUSR | S_IWUSR)
#define __DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize, _dstate) \
__DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \
carl9170_debugfs_##name ##_write, \
_read_bufsize, S_IRUSR | S_IWUSR, _dstate)
#define DEBUGFS_READONLY_FILE(name, _read_bufsize, fmt, value...) \
static char *carl9170_debugfs_ ##name ## _read(struct ar9170 *ar, \
char *buf, size_t buf_size,\
ssize_t *len) \
{ \
ADD(buf, *len, buf_size, fmt "\n", ##value); \
return buf; \
} \
DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize)
static char *carl9170_debugfs_mem_usage_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *len)
{
ADD(buf, *len, bufsize, "jar: [");
spin_lock_bh(&ar->mem_lock);
*len += bitmap_scnprintf(&buf[*len], bufsize - *len,
ar->mem_bitmap, ar->fw.mem_blocks);
ADD(buf, *len, bufsize, "]\n");
ADD(buf, *len, bufsize, "cookies: used:%3d / total:%3d, allocs:%d\n",
bitmap_weight(ar->mem_bitmap, ar->fw.mem_blocks),
ar->fw.mem_blocks, atomic_read(&ar->mem_allocs));
ADD(buf, *len, bufsize, "memory: free:%3d (%3d KiB) / total:%3d KiB)\n",
atomic_read(&ar->mem_free_blocks),
(atomic_read(&ar->mem_free_blocks) * ar->fw.mem_block_size) / 1024,
(ar->fw.mem_blocks * ar->fw.mem_block_size) / 1024);
spin_unlock_bh(&ar->mem_lock);
return buf;
}
DEBUGFS_DECLARE_RO_FILE(mem_usage, 512);
static char *carl9170_debugfs_qos_stat_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *len)
{
ADD(buf, *len, bufsize, "%s QoS AC\n", modparam_noht ? "Hardware" :
"Software");
ADD(buf, *len, bufsize, "[ VO VI "
" BE BK ]\n");
spin_lock_bh(&ar->tx_stats_lock);
ADD(buf, *len, bufsize, "[length/limit length/limit "
"length/limit length/limit ]\n"
"[ %3d/%3d %3d/%3d "
" %3d/%3d %3d/%3d ]\n\n",
ar->tx_stats[0].len, ar->tx_stats[0].limit,
ar->tx_stats[1].len, ar->tx_stats[1].limit,
ar->tx_stats[2].len, ar->tx_stats[2].limit,
ar->tx_stats[3].len, ar->tx_stats[3].limit);
ADD(buf, *len, bufsize, "[ total total "
" total total ]\n"
"[%10d %10d %10d %10d ]\n\n",
ar->tx_stats[0].count, ar->tx_stats[1].count,
ar->tx_stats[2].count, ar->tx_stats[3].count);
spin_unlock_bh(&ar->tx_stats_lock);
ADD(buf, *len, bufsize, "[ pend/waittx pend/waittx "
" pend/waittx pend/waittx]\n"
"[ %3d/%3d %3d/%3d "
" %3d/%3d %3d/%3d ]\n\n",
skb_queue_len(&ar->tx_pending[0]),
skb_queue_len(&ar->tx_status[0]),
skb_queue_len(&ar->tx_pending[1]),
skb_queue_len(&ar->tx_status[1]),
skb_queue_len(&ar->tx_pending[2]),
skb_queue_len(&ar->tx_status[2]),
skb_queue_len(&ar->tx_pending[3]),
skb_queue_len(&ar->tx_status[3]));
return buf;
}
DEBUGFS_DECLARE_RO_FILE(qos_stat, 512);
static void carl9170_debugfs_format_frame(struct ar9170 *ar,
struct sk_buff *skb, const char *prefix, char *buf,
ssize_t *off, ssize_t bufsize)
{
struct _carl9170_tx_superframe *txc = (void *) skb->data;
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
struct carl9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
struct ieee80211_hdr *hdr = (void *) txc->frame_data;
ADD(buf, *off, bufsize, "%s %p, c:%2x, DA:%pM, sq:%4d, mc:%.4x, "
"pc:%.8x, to:%d ms\n", prefix, skb, txc->s.cookie,
ieee80211_get_DA(hdr), get_seq_h(hdr),
le16_to_cpu(txc->f.mac_control), le32_to_cpu(txc->f.phy_control),
jiffies_to_msecs(jiffies - arinfo->timeout));
}
static char *carl9170_debugfs_ampdu_state_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *len)
{
struct carl9170_sta_tid *iter;
struct sk_buff *skb;
int cnt = 0, fc;
int offset;
rcu_read_lock();
list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
spin_lock_bh(&iter->lock);
ADD(buf, *len, bufsize, "Entry: #%2d TID:%1d, BSN:%4d, "
"SNX:%4d, HSN:%4d, BAW:%2d, state:%1d, toggles:%d\n",
cnt, iter->tid, iter->bsn, iter->snx, iter->hsn,
iter->max, iter->state, iter->counter);
ADD(buf, *len, bufsize, "\tWindow: [");
*len += bitmap_scnprintf(&buf[*len], bufsize - *len,
iter->bitmap, CARL9170_BAW_BITS);
#define BM_STR_OFF(offset) \
((CARL9170_BAW_BITS - (offset) - 1) / 4 + \
(CARL9170_BAW_BITS - (offset) - 1) / 32 + 1)
ADD(buf, *len, bufsize, ",W]\n");
offset = BM_STR_OFF(0);
ADD(buf, *len, bufsize, "\tBase Seq: %*s\n", offset, "T");
offset = BM_STR_OFF(SEQ_DIFF(iter->snx, iter->bsn));
ADD(buf, *len, bufsize, "\tNext Seq: %*s\n", offset, "W");
offset = BM_STR_OFF(((int)iter->hsn - (int)iter->bsn) %
CARL9170_BAW_BITS);
ADD(buf, *len, bufsize, "\tLast Seq: %*s\n", offset, "N");
ADD(buf, *len, bufsize, "\tPre-Aggregation reorder buffer: "
" currently queued:%d\n", skb_queue_len(&iter->queue));
fc = 0;
skb_queue_walk(&iter->queue, skb) {
char prefix[32];
snprintf(prefix, sizeof(prefix), "\t\t%3d :", fc);
carl9170_debugfs_format_frame(ar, skb, prefix, buf,
len, bufsize);
fc++;
}
spin_unlock_bh(&iter->lock);
cnt++;
}
rcu_read_unlock();
return buf;
}
DEBUGFS_DECLARE_RO_FILE(ampdu_state, 8000);
static void carl9170_debugfs_queue_dump(struct ar9170 *ar, char *buf,
ssize_t *len, size_t bufsize, struct sk_buff_head *queue)
{
struct sk_buff *skb;
char prefix[16];
int fc = 0;
spin_lock_bh(&queue->lock);
skb_queue_walk(queue, skb) {
snprintf(prefix, sizeof(prefix), "%3d :", fc);
carl9170_debugfs_format_frame(ar, skb, prefix, buf,
len, bufsize);
fc++;
}
spin_unlock_bh(&queue->lock);
}
#define DEBUGFS_QUEUE_DUMP(q, qi) \
static char *carl9170_debugfs_##q ##_##qi ##_read(struct ar9170 *ar, \
char *buf, size_t bufsize, ssize_t *len) \
{ \
carl9170_debugfs_queue_dump(ar, buf, len, bufsize, &ar->q[qi]); \
return buf; \
} \
DEBUGFS_DECLARE_RO_FILE(q##_##qi, 8000);
static char *carl9170_debugfs_sta_psm_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *len)
{
ADD(buf, *len, bufsize, "psm state: %s\n", (ar->ps.off_override ?
"FORCE CAM" : (ar->ps.state ? "PSM" : "CAM")));
ADD(buf, *len, bufsize, "sleep duration: %d ms.\n", ar->ps.sleep_ms);
ADD(buf, *len, bufsize, "last power-state transition: %d ms ago.\n",
jiffies_to_msecs(jiffies - ar->ps.last_action));
ADD(buf, *len, bufsize, "last CAM->PSM transition: %d ms ago.\n",
jiffies_to_msecs(jiffies - ar->ps.last_slept));
return buf;
}
DEBUGFS_DECLARE_RO_FILE(sta_psm, 160);
static char *carl9170_debugfs_tx_stuck_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *len)
{
int i;
for (i = 0; i < ar->hw->queues; i++) {
ADD(buf, *len, bufsize, "TX queue [%d]: %10d max:%10d ms.\n",
i, ieee80211_queue_stopped(ar->hw, i) ?
jiffies_to_msecs(jiffies - ar->queue_stop_timeout[i]) : 0,
jiffies_to_msecs(ar->max_queue_stop_timeout[i]));
ar->max_queue_stop_timeout[i] = 0;
}
return buf;
}
DEBUGFS_DECLARE_RO_FILE(tx_stuck, 180);
static char *carl9170_debugfs_phy_noise_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *len)
{
int err;
err = carl9170_get_noisefloor(ar);
if (err) {
*len = err;
return buf;
}
ADD(buf, *len, bufsize, "Chain 0: %10d dBm, ext. chan.:%10d dBm\n",
ar->noise[0], ar->noise[2]);
ADD(buf, *len, bufsize, "Chain 2: %10d dBm, ext. chan.:%10d dBm\n",
ar->noise[1], ar->noise[3]);
return buf;
}
DEBUGFS_DECLARE_RO_FILE(phy_noise, 180);
static char *carl9170_debugfs_vif_dump_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *len)
{
struct carl9170_vif_info *iter;
int i = 0;
ADD(buf, *len, bufsize, "registered VIFs:%d \\ %d\n",
ar->vifs, ar->fw.vif_num);
ADD(buf, *len, bufsize, "VIF bitmap: [");
*len += bitmap_scnprintf(&buf[*len], bufsize - *len,
&ar->vif_bitmap, ar->fw.vif_num);
ADD(buf, *len, bufsize, "]\n");
rcu_read_lock();
list_for_each_entry_rcu(iter, &ar->vif_list, list) {
struct ieee80211_vif *vif = carl9170_get_vif(iter);
ADD(buf, *len, bufsize, "\t%d = [%s VIF, id:%d, type:%x "
" mac:%pM %s]\n", i, (carl9170_get_main_vif(ar) == vif ?
"Master" : " Slave"), iter->id, vif->type, vif->addr,
iter->enable_beacon ? "beaconing " : "");
i++;
}
rcu_read_unlock();
return buf;
}
DEBUGFS_DECLARE_RO_FILE(vif_dump, 8000);
#define UPDATE_COUNTER(ar, name) ({ \
u32 __tmp[ARRAY_SIZE(name##_regs)]; \
unsigned int __i, __err = -ENODEV; \
\
for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) { \
__tmp[__i] = name##_regs[__i].reg; \
ar->debug.stats.name##_counter[__i] = 0; \
} \
\
if (IS_STARTED(ar)) \
__err = carl9170_read_mreg(ar, ARRAY_SIZE(name##_regs), \
__tmp, ar->debug.stats.name##_counter); \
(__err); })
#define TALLY_SUM_UP(ar, name) do { \
unsigned int __i; \
\
for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) { \
ar->debug.stats.name##_sum[__i] += \
ar->debug.stats.name##_counter[__i]; \
} \
} while (0)
#define DEBUGFS_HW_TALLY_FILE(name, f) \
static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \
char *dum, size_t bufsize, ssize_t *ret) \
{ \
char *buf; \
int i, max_len, err; \
\
max_len = ARRAY_SIZE(name##_regs) * 80; \
buf = vmalloc(max_len); \
if (!buf) \
return NULL; \
\
err = UPDATE_COUNTER(ar, name); \
if (err) { \
*ret = err; \
return buf; \
} \
\
TALLY_SUM_UP(ar, name); \
\
for (i = 0; i < ARRAY_SIZE(name##_regs); i++) { \
ADD(buf, *ret, max_len, "%22s = %" f "[+%" f "]\n", \
name##_regs[i].nreg, ar->debug.stats.name ##_sum[i],\
ar->debug.stats.name ##_counter[i]); \
} \
\
return buf; \
} \
DEBUGFS_DECLARE_RO_FILE(name, 0);
#define DEBUGFS_HW_REG_FILE(name, f) \
static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \
char *dum, size_t bufsize, ssize_t *ret) \
{ \
char *buf; \
int i, max_len, err; \
\
max_len = ARRAY_SIZE(name##_regs) * 80; \
buf = vmalloc(max_len); \
if (!buf) \
return NULL; \
\
err = UPDATE_COUNTER(ar, name); \
if (err) { \
*ret = err; \
return buf; \
} \
\
for (i = 0; i < ARRAY_SIZE(name##_regs); i++) { \
ADD(buf, *ret, max_len, "%22s = %" f "\n", \
name##_regs[i].nreg, \
ar->debug.stats.name##_counter[i]); \
} \
\
return buf; \
} \
DEBUGFS_DECLARE_RO_FILE(name, 0);
static ssize_t carl9170_debugfs_hw_ioread32_write(struct ar9170 *ar,
const char *buf, size_t count)
{
int err = 0, i, n = 0, max_len = 32, res;
unsigned int reg, tmp;
if (!count)
return 0;
if (count > max_len)
return -E2BIG;
res = sscanf(buf, "0x%X %d", &reg, &n);
if (res < 1) {
err = -EINVAL;
goto out;
}
if (res == 1)
n = 1;
if (n > 15) {
err = -EMSGSIZE;
goto out;
}
if ((reg >= 0x280000) || ((reg + (n << 2)) >= 0x280000)) {
err = -EADDRNOTAVAIL;
goto out;
}
if (reg & 3) {
err = -EINVAL;
goto out;
}
for (i = 0; i < n; i++) {
err = carl9170_read_reg(ar, reg + (i << 2), &tmp);
if (err)
goto out;
ar->debug.ring[ar->debug.ring_tail].reg = reg + (i << 2);
ar->debug.ring[ar->debug.ring_tail].value = tmp;
ar->debug.ring_tail++;
ar->debug.ring_tail %= CARL9170_DEBUG_RING_SIZE;
}
out:
return err ? err : count;
}
static char *carl9170_debugfs_hw_ioread32_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *ret)
{
int i = 0;
while (ar->debug.ring_head != ar->debug.ring_tail) {
ADD(buf, *ret, bufsize, "%.8x = %.8x\n",
ar->debug.ring[ar->debug.ring_head].reg,
ar->debug.ring[ar->debug.ring_head].value);
ar->debug.ring_head++;
ar->debug.ring_head %= CARL9170_DEBUG_RING_SIZE;
if (i++ == 64)
break;
}
ar->debug.ring_head = ar->debug.ring_tail;
return buf;
}
DEBUGFS_DECLARE_RW_FILE(hw_ioread32, CARL9170_DEBUG_RING_SIZE * 40);
static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
size_t count)
{
int err;
if (count < 1)
return -EINVAL;
switch (buf[0]) {
case 'F':
ar->needs_full_reset = true;
break;
case 'R':
if (!IS_STARTED(ar)) {
err = -EAGAIN;
goto out;
}
ar->needs_full_reset = false;
break;
case 'M':
err = carl9170_mac_reset(ar);
if (err < 0)
count = err;
goto out;
case 'P':
err = carl9170_set_channel(ar, ar->hw->conf.channel,
ar->hw->conf.channel_type, CARL9170_RFI_COLD);
if (err < 0)
count = err;
goto out;
default:
return -EINVAL;
}
carl9170_restart(ar, CARL9170_RR_USER_REQUEST);
out:
return count;
}
static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *ret)
{
ADD(buf, *ret, bufsize, "[P]hy reinit, [R]estart, [F]ull usb reset, "
"[M]ac reset\n");
ADD(buf, *ret, bufsize, "firmware restarts:%d, last reason:%d\n",
ar->restart_counter, ar->last_reason);
ADD(buf, *ret, bufsize, "phy reinit errors:%d (%d)\n",
ar->total_chan_fail, ar->chan_fail);
ADD(buf, *ret, bufsize, "reported firmware errors:%d\n",
ar->fw.err_counter);
ADD(buf, *ret, bufsize, "reported firmware BUGs:%d\n",
ar->fw.bug_counter);
ADD(buf, *ret, bufsize, "pending restart requests:%d\n",
atomic_read(&ar->pending_restarts));
return buf;
}
__DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED);
static const char *const erp_modes[] = {
[CARL9170_ERP_INVALID] = "INVALID",
[CARL9170_ERP_AUTO] = "Automatic",
[CARL9170_ERP_MAC80211] = "Set by MAC80211",
[CARL9170_ERP_OFF] = "Force Off",
[CARL9170_ERP_RTS] = "Force RTS",
[CARL9170_ERP_CTS] = "Force CTS"
};
static char *carl9170_debugfs_erp_read(struct ar9170 *ar, char *buf,
size_t bufsize, ssize_t *ret)
{
ADD(buf, *ret, bufsize, "ERP Setting: (%d) -> %s\n", ar->erp_mode,
erp_modes[ar->erp_mode]);
return buf;
}
static ssize_t carl9170_debugfs_erp_write(struct ar9170 *ar, const char *buf,
size_t count)
{
int res, val;
if (count < 1)
return -EINVAL;
res = sscanf(buf, "%d", &val);
if (res != 1)
return -EINVAL;
if (!((val > CARL9170_ERP_INVALID) &&
(val < __CARL9170_ERP_NUM)))
return -EINVAL;
ar->erp_mode = val;
return count;
}
DEBUGFS_DECLARE_RW_FILE(erp, 80);
static ssize_t carl9170_debugfs_hw_iowrite32_write(struct ar9170 *ar,
const char *buf, size_t count)
{
int err = 0, max_len = 22, res;
u32 reg, val;
if (!count)
return 0;
if (count > max_len)
return -E2BIG;
res = sscanf(buf, "0x%X 0x%X", &reg, &val);
if (res != 2) {
err = -EINVAL;
goto out;
}
if (reg <= 0x100000 || reg >= 0x280000) {
err = -EADDRNOTAVAIL;
goto out;
}
if (reg & 3) {
err = -EINVAL;
goto out;
}
err = carl9170_write_reg(ar, reg, val);
if (err)
goto out;
out:
return err ? err : count;
}
DEBUGFS_DECLARE_WO_FILE(hw_iowrite32);
DEBUGFS_HW_TALLY_FILE(hw_tx_tally, "u");
DEBUGFS_HW_TALLY_FILE(hw_rx_tally, "u");
DEBUGFS_HW_TALLY_FILE(hw_phy_errors, "u");
DEBUGFS_HW_REG_FILE(hw_wlan_queue, ".8x");
DEBUGFS_HW_REG_FILE(hw_pta_queue, ".8x");
DEBUGFS_HW_REG_FILE(hw_ampdu_info, ".8x");
DEBUGFS_QUEUE_DUMP(tx_status, 0);
DEBUGFS_QUEUE_DUMP(tx_status, 1);
DEBUGFS_QUEUE_DUMP(tx_status, 2);
DEBUGFS_QUEUE_DUMP(tx_status, 3);
DEBUGFS_QUEUE_DUMP(tx_pending, 0);
DEBUGFS_QUEUE_DUMP(tx_pending, 1);
DEBUGFS_QUEUE_DUMP(tx_pending, 2);
DEBUGFS_QUEUE_DUMP(tx_pending, 3);
DEBUGFS_READONLY_FILE(usb_tx_anch_urbs, 20, "%d",
atomic_read(&ar->tx_anch_urbs));
DEBUGFS_READONLY_FILE(usb_rx_anch_urbs, 20, "%d",
atomic_read(&ar->rx_anch_urbs));
DEBUGFS_READONLY_FILE(usb_rx_work_urbs, 20, "%d",
atomic_read(&ar->rx_work_urbs));
DEBUGFS_READONLY_FILE(usb_rx_pool_urbs, 20, "%d",
atomic_read(&ar->rx_pool_urbs));
DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d",
atomic_read(&ar->tx_total_queued));
DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d",
atomic_read(&ar->tx_ampdu_scheduler));
DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d",
atomic_read(&ar->tx_total_pending));
DEBUGFS_READONLY_FILE(tx_ampdu_list_len, 20, "%d",
ar->tx_ampdu_list_len);
DEBUGFS_READONLY_FILE(tx_ampdu_upload, 20, "%d",
atomic_read(&ar->tx_ampdu_upload));
DEBUGFS_READONLY_FILE(tx_janitor_last_run, 64, "last run:%d ms ago",
jiffies_to_msecs(jiffies - ar->tx_janitor_last_run));
DEBUGFS_READONLY_FILE(tx_dropped, 20, "%d", ar->tx_dropped);
DEBUGFS_READONLY_FILE(rx_dropped, 20, "%d", ar->rx_dropped);
DEBUGFS_READONLY_FILE(sniffer_enabled, 20, "%d", ar->sniffer_enabled);
DEBUGFS_READONLY_FILE(rx_software_decryption, 20, "%d",
ar->rx_software_decryption);
DEBUGFS_READONLY_FILE(ampdu_factor, 20, "%d",
ar->current_factor);
DEBUGFS_READONLY_FILE(ampdu_density, 20, "%d",
ar->current_density);
DEBUGFS_READONLY_FILE(beacon_int, 20, "%d TU", ar->global_beacon_int);
DEBUGFS_READONLY_FILE(pretbtt, 20, "%d TU", ar->global_pretbtt);
void carl9170_debugfs_register(struct ar9170 *ar)
{
ar->debug_dir = debugfs_create_dir(KBUILD_MODNAME,
ar->hw->wiphy->debugfsdir);
#define DEBUGFS_ADD(name) \
debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr, \
ar->debug_dir, ar, \
&carl_debugfs_##name ## _ops.fops);
DEBUGFS_ADD(usb_tx_anch_urbs);
DEBUGFS_ADD(usb_rx_pool_urbs);
DEBUGFS_ADD(usb_rx_anch_urbs);
DEBUGFS_ADD(usb_rx_work_urbs);
DEBUGFS_ADD(tx_total_queued);
DEBUGFS_ADD(tx_total_pending);
DEBUGFS_ADD(tx_dropped);
DEBUGFS_ADD(tx_stuck);
DEBUGFS_ADD(tx_ampdu_upload);
DEBUGFS_ADD(tx_ampdu_scheduler);
DEBUGFS_ADD(tx_ampdu_list_len);
DEBUGFS_ADD(rx_dropped);
DEBUGFS_ADD(sniffer_enabled);
DEBUGFS_ADD(rx_software_decryption);
DEBUGFS_ADD(mem_usage);
DEBUGFS_ADD(qos_stat);
DEBUGFS_ADD(sta_psm);
DEBUGFS_ADD(ampdu_state);
DEBUGFS_ADD(hw_tx_tally);
DEBUGFS_ADD(hw_rx_tally);
DEBUGFS_ADD(hw_phy_errors);
DEBUGFS_ADD(phy_noise);
DEBUGFS_ADD(hw_wlan_queue);
DEBUGFS_ADD(hw_pta_queue);
DEBUGFS_ADD(hw_ampdu_info);
DEBUGFS_ADD(ampdu_density);
DEBUGFS_ADD(ampdu_factor);
DEBUGFS_ADD(tx_janitor_last_run);
DEBUGFS_ADD(tx_status_0);
DEBUGFS_ADD(tx_status_1);
DEBUGFS_ADD(tx_status_2);
DEBUGFS_ADD(tx_status_3);
DEBUGFS_ADD(tx_pending_0);
DEBUGFS_ADD(tx_pending_1);
DEBUGFS_ADD(tx_pending_2);
DEBUGFS_ADD(tx_pending_3);
DEBUGFS_ADD(hw_ioread32);
DEBUGFS_ADD(hw_iowrite32);
DEBUGFS_ADD(bug);
DEBUGFS_ADD(erp);
DEBUGFS_ADD(vif_dump);
DEBUGFS_ADD(beacon_int);
DEBUGFS_ADD(pretbtt);
#undef DEBUGFS_ADD
}
void carl9170_debugfs_unregister(struct ar9170 *ar)
{
debugfs_remove_recursive(ar->debug_dir);
}

View File

@@ -0,0 +1,134 @@
/*
* Atheros CARL9170 driver
*
* debug header
*
* Copyright 2010, Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#ifndef __DEBUG_H
#define __DEBUG_H
#include "eeprom.h"
#include "wlan.h"
#include "hw.h"
#include "fwdesc.h"
#include "fwcmd.h"
#include "../regd.h"
struct hw_stat_reg_entry {
u32 reg;
char nreg[32];
};
#define STAT_MAC_REG(reg) \
{ (AR9170_MAC_REG_##reg), #reg }
#define STAT_PTA_REG(reg) \
{ (AR9170_PTA_REG_##reg), #reg }
#define STAT_USB_REG(reg) \
{ (AR9170_USB_REG_##reg), #reg }
static const struct hw_stat_reg_entry hw_rx_tally_regs[] = {
STAT_MAC_REG(RX_CRC32), STAT_MAC_REG(RX_CRC16),
STAT_MAC_REG(RX_TIMEOUT_COUNT), STAT_MAC_REG(RX_ERR_DECRYPTION_UNI),
STAT_MAC_REG(RX_ERR_DECRYPTION_MUL), STAT_MAC_REG(RX_MPDU),
STAT_MAC_REG(RX_DROPPED_MPDU), STAT_MAC_REG(RX_DEL_MPDU),
};
static const struct hw_stat_reg_entry hw_phy_errors_regs[] = {
STAT_MAC_REG(RX_PHY_MISC_ERROR), STAT_MAC_REG(RX_PHY_XR_ERROR),
STAT_MAC_REG(RX_PHY_OFDM_ERROR), STAT_MAC_REG(RX_PHY_CCK_ERROR),
STAT_MAC_REG(RX_PHY_HT_ERROR), STAT_MAC_REG(RX_PHY_TOTAL),
};
static const struct hw_stat_reg_entry hw_tx_tally_regs[] = {
STAT_MAC_REG(TX_TOTAL), STAT_MAC_REG(TX_UNDERRUN),
STAT_MAC_REG(TX_RETRY),
};
static const struct hw_stat_reg_entry hw_wlan_queue_regs[] = {
STAT_MAC_REG(DMA_STATUS), STAT_MAC_REG(DMA_TRIGGER),
STAT_MAC_REG(DMA_TXQ0_ADDR), STAT_MAC_REG(DMA_TXQ0_CURR_ADDR),
STAT_MAC_REG(DMA_TXQ1_ADDR), STAT_MAC_REG(DMA_TXQ1_CURR_ADDR),
STAT_MAC_REG(DMA_TXQ2_ADDR), STAT_MAC_REG(DMA_TXQ2_CURR_ADDR),
STAT_MAC_REG(DMA_TXQ3_ADDR), STAT_MAC_REG(DMA_TXQ3_CURR_ADDR),
STAT_MAC_REG(DMA_RXQ_ADDR), STAT_MAC_REG(DMA_RXQ_CURR_ADDR),
};
static const struct hw_stat_reg_entry hw_ampdu_info_regs[] = {
STAT_MAC_REG(AMPDU_DENSITY), STAT_MAC_REG(AMPDU_FACTOR),
};
static const struct hw_stat_reg_entry hw_pta_queue_regs[] = {
STAT_PTA_REG(DN_CURR_ADDRH), STAT_PTA_REG(DN_CURR_ADDRL),
STAT_PTA_REG(UP_CURR_ADDRH), STAT_PTA_REG(UP_CURR_ADDRL),
STAT_PTA_REG(DMA_STATUS), STAT_PTA_REG(DMA_MODE_CTRL),
};
#define DEFINE_TALLY(name) \
u32 name##_sum[ARRAY_SIZE(name##_regs)], \
name##_counter[ARRAY_SIZE(name##_regs)] \
#define DEFINE_STAT(name) \
u32 name##_counter[ARRAY_SIZE(name##_regs)] \
struct ath_stats {
DEFINE_TALLY(hw_tx_tally);
DEFINE_TALLY(hw_rx_tally);
DEFINE_TALLY(hw_phy_errors);
DEFINE_STAT(hw_wlan_queue);
DEFINE_STAT(hw_pta_queue);
DEFINE_STAT(hw_ampdu_info);
};
struct carl9170_debug_mem_rbe {
u32 reg;
u32 value;
};
#define CARL9170_DEBUG_RING_SIZE 64
struct carl9170_debug {
struct ath_stats stats;
struct carl9170_debug_mem_rbe ring[CARL9170_DEBUG_RING_SIZE];
struct mutex ring_lock;
unsigned int ring_head, ring_tail;
struct delayed_work update_tally;
};
struct ar9170;
void carl9170_debugfs_register(struct ar9170 *ar);
void carl9170_debugfs_unregister(struct ar9170 *ar);
#endif /* __DEBUG_H */

View File

@@ -0,0 +1,216 @@
/*
* Shared Atheros AR9170 Header
*
* EEPROM layout
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#ifndef __CARL9170_SHARED_EEPROM_H
#define __CARL9170_SHARED_EEPROM_H
#define AR9170_EEPROM_START 0x1600
#define AR5416_MAX_CHAINS 2
#define AR5416_MODAL_SPURS 5
struct ar9170_eeprom_modal {
__le32 antCtrlChain[AR5416_MAX_CHAINS];
__le32 antCtrlCommon;
s8 antennaGainCh[AR5416_MAX_CHAINS];
u8 switchSettling;
u8 txRxAttenCh[AR5416_MAX_CHAINS];
u8 rxTxMarginCh[AR5416_MAX_CHAINS];
s8 adcDesiredSize;
s8 pgaDesiredSize;
u8 xlnaGainCh[AR5416_MAX_CHAINS];
u8 txEndToXpaOff;
u8 txEndToRxOn;
u8 txFrameToXpaOn;
u8 thresh62;
s8 noiseFloorThreshCh[AR5416_MAX_CHAINS];
u8 xpdGain;
u8 xpd;
s8 iqCalICh[AR5416_MAX_CHAINS];
s8 iqCalQCh[AR5416_MAX_CHAINS];
u8 pdGainOverlap;
u8 ob;
u8 db;
u8 xpaBiasLvl;
u8 pwrDecreaseFor2Chain;
u8 pwrDecreaseFor3Chain;
u8 txFrameToDataStart;
u8 txFrameToPaOn;
u8 ht40PowerIncForPdadc;
u8 bswAtten[AR5416_MAX_CHAINS];
u8 bswMargin[AR5416_MAX_CHAINS];
u8 swSettleHt40;
u8 reserved[22];
struct spur_channel {
__le16 spurChan;
u8 spurRangeLow;
u8 spurRangeHigh;
} __packed spur_channels[AR5416_MODAL_SPURS];
} __packed;
#define AR5416_NUM_PD_GAINS 4
#define AR5416_PD_GAIN_ICEPTS 5
struct ar9170_calibration_data_per_freq {
u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
} __packed;
#define AR5416_NUM_5G_CAL_PIERS 8
#define AR5416_NUM_2G_CAL_PIERS 4
#define AR5416_NUM_5G_TARGET_PWRS 8
#define AR5416_NUM_2G_CCK_TARGET_PWRS 3
#define AR5416_NUM_2G_OFDM_TARGET_PWRS 4
#define AR5416_MAX_NUM_TGT_PWRS 8
struct ar9170_calibration_target_power_legacy {
u8 freq;
u8 power[4];
} __packed;
struct ar9170_calibration_target_power_ht {
u8 freq;
u8 power[8];
} __packed;
#define AR5416_NUM_CTLS 24
struct ar9170_calctl_edges {
u8 channel;
#define AR9170_CALCTL_EDGE_FLAGS 0xC0
u8 power_flags;
} __packed;
#define AR5416_NUM_BAND_EDGES 8
struct ar9170_calctl_data {
struct ar9170_calctl_edges
control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
} __packed;
struct ar9170_eeprom {
__le16 length;
__le16 checksum;
__le16 version;
u8 operating_flags;
#define AR9170_OPFLAG_5GHZ 1
#define AR9170_OPFLAG_2GHZ 2
u8 misc;
__le16 reg_domain[2];
u8 mac_address[6];
u8 rx_mask;
u8 tx_mask;
__le16 rf_silent;
__le16 bluetooth_options;
__le16 device_capabilities;
__le32 build_number;
u8 deviceType;
u8 reserved[33];
u8 customer_data[64];
struct ar9170_eeprom_modal
modal_header[2];
u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS];
u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS];
struct ar9170_calibration_data_per_freq
cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS],
cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
/* power calibration data */
struct ar9170_calibration_target_power_legacy
cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS];
struct ar9170_calibration_target_power_ht
cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS],
cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS];
struct ar9170_calibration_target_power_legacy
cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS],
cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS];
struct ar9170_calibration_target_power_ht
cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS],
cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS];
/* conformance testing limits */
u8 ctl_index[AR5416_NUM_CTLS];
struct ar9170_calctl_data
ctl_data[AR5416_NUM_CTLS];
u8 pad;
__le16 subsystem_id;
} __packed;
#define AR9170_LED_MODE_POWER_ON 0x0001
#define AR9170_LED_MODE_RESERVED 0x0002
#define AR9170_LED_MODE_DISABLE_STATE 0x0004
#define AR9170_LED_MODE_OFF_IN_PSM 0x0008
/* AR9170_LED_MODE BIT is set */
#define AR9170_LED_MODE_FREQUENCY_S 4
#define AR9170_LED_MODE_FREQUENCY 0x0030
#define AR9170_LED_MODE_FREQUENCY_1HZ 0x0000
#define AR9170_LED_MODE_FREQUENCY_0_5HZ 0x0010
#define AR9170_LED_MODE_FREQUENCY_0_25HZ 0x0020
#define AR9170_LED_MODE_FREQUENCY_0_125HZ 0x0030
/* AR9170_LED_MODE BIT is not set */
#define AR9170_LED_MODE_CONN_STATE_S 4
#define AR9170_LED_MODE_CONN_STATE 0x0030
#define AR9170_LED_MODE_CONN_STATE_FORCE_OFF 0x0000
#define AR9170_LED_MODE_CONN_STATE_FORCE_ON 0x0010
/* Idle off / Active on */
#define AR9170_LED_MODE_CONN_STATE_IOFF_AON 0x0020
/* Idle on / Active off */
#define AR9170_LED_MODE_CONN_STATE_ION_AOFF 0x0010
#define AR9170_LED_MODE_MODE 0x0040
#define AR9170_LED_MODE_RESERVED2 0x0080
#define AR9170_LED_MODE_TON_SCAN_S 8
#define AR9170_LED_MODE_TON_SCAN 0x0f00
#define AR9170_LED_MODE_TOFF_SCAN_S 12
#define AR9170_LED_MODE_TOFF_SCAN 0xf000
struct ar9170_led_mode {
__le16 led;
};
#endif /* __CARL9170_SHARED_EEPROM_H */

View File

@@ -0,0 +1,434 @@
/*
* Atheros CARL9170 driver
*
* firmware parser
*
* Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*/
#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/crc32.h>
#include <linux/module.h>
#include "carl9170.h"
#include "fwcmd.h"
#include "version.h"
static const u8 otus_magic[4] = { OTUS_MAGIC };
static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4],
const unsigned int len, const u8 compatible_revision)
{
const struct carl9170fw_desc_head *iter;
carl9170fw_for_each_hdr(iter, ar->fw.desc) {
if (carl9170fw_desc_cmp(iter, descid, len,
compatible_revision))
return (void *)iter;
}
/* needed to find the LAST desc */
if (carl9170fw_desc_cmp(iter, descid, len,
compatible_revision))
return (void *)iter;
return NULL;
}
static int carl9170_fw_verify_descs(struct ar9170 *ar,
const struct carl9170fw_desc_head *head, unsigned int max_len)
{
const struct carl9170fw_desc_head *pos;
unsigned long pos_addr, end_addr;
unsigned int pos_length;
if (max_len < sizeof(*pos))
return -ENODATA;
max_len = min_t(unsigned int, CARL9170FW_DESC_MAX_LENGTH, max_len);
pos = head;
pos_addr = (unsigned long) pos;
end_addr = pos_addr + max_len;
while (pos_addr < end_addr) {
if (pos_addr + sizeof(*head) > end_addr)
return -E2BIG;
pos_length = le16_to_cpu(pos->length);
if (pos_length < sizeof(*head))
return -EBADMSG;
if (pos_length > max_len)
return -EOVERFLOW;
if (pos_addr + pos_length > end_addr)
return -EMSGSIZE;
if (carl9170fw_desc_cmp(pos, LAST_MAGIC,
CARL9170FW_LAST_DESC_SIZE,
CARL9170FW_LAST_DESC_CUR_VER))
return 0;
pos_addr += pos_length;
pos = (void *)pos_addr;
max_len -= pos_length;
}
return -EINVAL;
}
static void carl9170_fw_info(struct ar9170 *ar)
{
const struct carl9170fw_motd_desc *motd_desc;
unsigned int str_ver_len;
u32 fw_date;
dev_info(&ar->udev->dev, "driver API: %s 2%03d-%02d-%02d [%d-%d]\n",
CARL9170FW_VERSION_GIT, CARL9170FW_VERSION_YEAR,
CARL9170FW_VERSION_MONTH, CARL9170FW_VERSION_DAY,
CARL9170FW_API_MIN_VER, CARL9170FW_API_MAX_VER);
motd_desc = carl9170_fw_find_desc(ar, MOTD_MAGIC,
sizeof(*motd_desc), CARL9170FW_MOTD_DESC_CUR_VER);
if (motd_desc) {
str_ver_len = strnlen(motd_desc->release,
CARL9170FW_MOTD_RELEASE_LEN);
fw_date = le32_to_cpu(motd_desc->fw_year_month_day);
dev_info(&ar->udev->dev, "firmware API: %.*s 2%03d-%02d-%02d\n",
str_ver_len, motd_desc->release,
CARL9170FW_GET_YEAR(fw_date),
CARL9170FW_GET_MONTH(fw_date),
CARL9170FW_GET_DAY(fw_date));
strlcpy(ar->hw->wiphy->fw_version, motd_desc->release,
sizeof(ar->hw->wiphy->fw_version));
}
}
static bool valid_dma_addr(const u32 address)
{
if (address >= AR9170_SRAM_OFFSET &&
address < (AR9170_SRAM_OFFSET + AR9170_SRAM_SIZE))
return true;
return false;
}
static bool valid_cpu_addr(const u32 address)
{
if (valid_dma_addr(address) || (address >= AR9170_PRAM_OFFSET &&
address < (AR9170_PRAM_OFFSET + AR9170_PRAM_SIZE)))
return true;
return false;
}
static int carl9170_fw_checksum(struct ar9170 *ar, const __u8 *data,
size_t len)
{
const struct carl9170fw_otus_desc *otus_desc;
const struct carl9170fw_last_desc *last_desc;
const struct carl9170fw_chk_desc *chk_desc;
unsigned long fin, diff;
unsigned int dsc_len;
u32 crc32;
last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC,
sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER);
if (!last_desc)
return -EINVAL;
otus_desc = carl9170_fw_find_desc(ar, OTUS_MAGIC,
sizeof(*otus_desc), CARL9170FW_OTUS_DESC_CUR_VER);
if (!otus_desc) {
dev_err(&ar->udev->dev, "failed to find compatible firmware "
"descriptor.\n");
return -ENODATA;
}
chk_desc = carl9170_fw_find_desc(ar, CHK_MAGIC,
sizeof(*chk_desc), CARL9170FW_CHK_DESC_CUR_VER);
if (!chk_desc) {
dev_warn(&ar->udev->dev, "Unprotected firmware image.\n");
return 0;
}
dsc_len = min_t(unsigned int, len,
(unsigned long)chk_desc - (unsigned long)otus_desc);
fin = (unsigned long) last_desc + sizeof(*last_desc);
diff = fin - (unsigned long) otus_desc;
if (diff < len)
len -= diff;
if (len < 256)
return -EIO;
crc32 = crc32_le(~0, data, len);
if (cpu_to_le32(crc32) != chk_desc->fw_crc32) {
dev_err(&ar->udev->dev, "fw checksum test failed.\n");
return -ENOEXEC;
}
crc32 = crc32_le(crc32, (void *)otus_desc, dsc_len);
if (cpu_to_le32(crc32) != chk_desc->hdr_crc32) {
dev_err(&ar->udev->dev, "descriptor check failed.\n");
return -EINVAL;
}
return 0;
}
static int carl9170_fw_tx_sequence(struct ar9170 *ar)
{
const struct carl9170fw_txsq_desc *txsq_desc;
txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC, sizeof(*txsq_desc),
CARL9170FW_TXSQ_DESC_CUR_VER);
if (txsq_desc) {
ar->fw.tx_seq_table = le32_to_cpu(txsq_desc->seq_table_addr);
if (!valid_cpu_addr(ar->fw.tx_seq_table))
return -EINVAL;
} else {
ar->fw.tx_seq_table = 0;
}
return 0;
}
static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
{
const struct carl9170fw_otus_desc *otus_desc;
int err;
u16 if_comb_types;
err = carl9170_fw_checksum(ar, data, len);
if (err)
return err;
otus_desc = carl9170_fw_find_desc(ar, OTUS_MAGIC,
sizeof(*otus_desc), CARL9170FW_OTUS_DESC_CUR_VER);
if (!otus_desc) {
return -ENODATA;
}
#define SUPP(feat) \
(carl9170fw_supports(otus_desc->feature_set, feat))
if (!SUPP(CARL9170FW_DUMMY_FEATURE)) {
dev_err(&ar->udev->dev, "invalid firmware descriptor "
"format detected.\n");
return -EINVAL;
}
ar->fw.api_version = otus_desc->api_ver;
if (ar->fw.api_version < CARL9170FW_API_MIN_VER ||
ar->fw.api_version > CARL9170FW_API_MAX_VER) {
dev_err(&ar->udev->dev, "unsupported firmware api version.\n");
return -EINVAL;
}
if (!SUPP(CARL9170FW_COMMAND_PHY) || SUPP(CARL9170FW_UNUSABLE) ||
!SUPP(CARL9170FW_HANDLE_BACK_REQ)) {
dev_err(&ar->udev->dev, "firmware does support "
"mandatory features.\n");
return -ECANCELED;
}
if (ilog2(le32_to_cpu(otus_desc->feature_set)) >=
__CARL9170FW_FEATURE_NUM) {
dev_warn(&ar->udev->dev, "driver does not support all "
"firmware features.\n");
}
if (!SUPP(CARL9170FW_COMMAND_CAM)) {
dev_info(&ar->udev->dev, "crypto offloading is disabled "
"by firmware.\n");
ar->disable_offload = true;
}
if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM))
ar->hw->flags |= IEEE80211_HW_SUPPORTS_PS;
if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) {
dev_err(&ar->udev->dev, "firmware does not provide "
"mandatory interfaces.\n");
return -EINVAL;
}
if (SUPP(CARL9170FW_MINIBOOT))
ar->fw.offset = le16_to_cpu(otus_desc->miniboot_size);
else
ar->fw.offset = 0;
if (SUPP(CARL9170FW_USB_DOWN_STREAM)) {
ar->hw->extra_tx_headroom += sizeof(struct ar9170_stream);
ar->fw.tx_stream = true;
}
if (SUPP(CARL9170FW_USB_UP_STREAM))
ar->fw.rx_stream = true;
if (SUPP(CARL9170FW_RX_FILTER)) {
ar->fw.rx_filter = true;
ar->rx_filter_caps = FIF_FCSFAIL | FIF_PLCPFAIL |
FIF_CONTROL | FIF_PSPOLL | FIF_OTHER_BSS |
FIF_PROMISC_IN_BSS;
}
if (SUPP(CARL9170FW_HW_COUNTERS))
ar->fw.hw_counters = true;
if (SUPP(CARL9170FW_WOL))
device_set_wakeup_enable(&ar->udev->dev, true);
if (SUPP(CARL9170FW_RX_BA_FILTER))
ar->fw.ba_filter = true;
if_comb_types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT);
ar->fw.vif_num = otus_desc->vif_num;
ar->fw.cmd_bufs = otus_desc->cmd_bufs;
ar->fw.address = le32_to_cpu(otus_desc->fw_address);
ar->fw.rx_size = le16_to_cpu(otus_desc->rx_max_frame_len);
ar->fw.mem_blocks = min_t(unsigned int, otus_desc->tx_descs, 0xfe);
atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks);
ar->fw.mem_block_size = le16_to_cpu(otus_desc->tx_frag_len);
if (ar->fw.vif_num >= AR9170_MAX_VIRTUAL_MAC || !ar->fw.vif_num ||
ar->fw.mem_blocks < 16 || !ar->fw.cmd_bufs ||
ar->fw.mem_block_size < 64 || ar->fw.mem_block_size > 512 ||
ar->fw.rx_size > 32768 || ar->fw.rx_size < 4096 ||
!valid_cpu_addr(ar->fw.address)) {
dev_err(&ar->udev->dev, "firmware shows obvious signs of "
"malicious tampering.\n");
return -EINVAL;
}
ar->fw.beacon_addr = le32_to_cpu(otus_desc->bcn_addr);
ar->fw.beacon_max_len = le16_to_cpu(otus_desc->bcn_len);
if (valid_dma_addr(ar->fw.beacon_addr) && ar->fw.beacon_max_len >=
AR9170_MAC_BCN_LENGTH_MAX) {
ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
if (SUPP(CARL9170FW_WLANTX_CAB)) {
if_comb_types |=
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO);
#ifdef CONFIG_MAC80211_MESH
if_comb_types |=
BIT(NL80211_IFTYPE_MESH_POINT);
#endif /* CONFIG_MAC80211_MESH */
}
}
ar->if_comb_limits[0].max = ar->fw.vif_num;
ar->if_comb_limits[0].types = if_comb_types;
ar->if_combs[0].num_different_channels = 1;
ar->if_combs[0].max_interfaces = ar->fw.vif_num;
ar->if_combs[0].limits = ar->if_comb_limits;
ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits);
ar->hw->wiphy->iface_combinations = ar->if_combs;
ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs);
ar->hw->wiphy->interface_modes |= if_comb_types;
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
#undef SUPPORTED
return carl9170_fw_tx_sequence(ar);
}
static struct carl9170fw_desc_head *
carl9170_find_fw_desc(struct ar9170 *ar, const __u8 *fw_data, const size_t len)
{
int scan = 0, found = 0;
if (!carl9170fw_size_check(len)) {
dev_err(&ar->udev->dev, "firmware size is out of bound.\n");
return NULL;
}
while (scan < len - sizeof(struct carl9170fw_desc_head)) {
if (fw_data[scan++] == otus_magic[found])
found++;
else
found = 0;
if (scan >= len)
break;
if (found == sizeof(otus_magic))
break;
}
if (found != sizeof(otus_magic))
return NULL;
return (void *)&fw_data[scan - found];
}
int carl9170_parse_firmware(struct ar9170 *ar)
{
const struct carl9170fw_desc_head *fw_desc = NULL;
const struct firmware *fw = ar->fw.fw;
unsigned long header_offset = 0;
int err;
if (WARN_ON(!fw))
return -EINVAL;
fw_desc = carl9170_find_fw_desc(ar, fw->data, fw->size);
if (!fw_desc) {
dev_err(&ar->udev->dev, "unsupported firmware.\n");
return -ENODATA;
}
header_offset = (unsigned long)fw_desc - (unsigned long)fw->data;
err = carl9170_fw_verify_descs(ar, fw_desc, fw->size - header_offset);
if (err) {
dev_err(&ar->udev->dev, "damaged firmware (%d).\n", err);
return err;
}
ar->fw.desc = fw_desc;
carl9170_fw_info(ar);
err = carl9170_fw(ar, fw->data, fw->size);
if (err) {
dev_err(&ar->udev->dev, "failed to parse firmware (%d).\n",
err);
return err;
}
return 0;
}

View File

@@ -0,0 +1,318 @@
/*
* Shared Atheros AR9170 Header
*
* Firmware command interface definitions
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#ifndef __CARL9170_SHARED_FWCMD_H
#define __CARL9170_SHARED_FWCMD_H
#define CARL9170_MAX_CMD_LEN 64
#define CARL9170_MAX_CMD_PAYLOAD_LEN 60
#define CARL9170FW_API_MIN_VER 1
#define CARL9170FW_API_MAX_VER 1
enum carl9170_cmd_oids {
CARL9170_CMD_RREG = 0x00,
CARL9170_CMD_WREG = 0x01,
CARL9170_CMD_ECHO = 0x02,
CARL9170_CMD_SWRST = 0x03,
CARL9170_CMD_REBOOT = 0x04,
CARL9170_CMD_BCN_CTRL = 0x05,
CARL9170_CMD_READ_TSF = 0x06,
CARL9170_CMD_RX_FILTER = 0x07,
CARL9170_CMD_WOL = 0x08,
CARL9170_CMD_TALLY = 0x09,
/* CAM */
CARL9170_CMD_EKEY = 0x10,
CARL9170_CMD_DKEY = 0x11,
/* RF / PHY */
CARL9170_CMD_FREQUENCY = 0x20,
CARL9170_CMD_RF_INIT = 0x21,
CARL9170_CMD_SYNTH = 0x22,
CARL9170_CMD_FREQ_START = 0x23,
CARL9170_CMD_PSM = 0x24,
/* Asychronous command flag */
CARL9170_CMD_ASYNC_FLAG = 0x40,
CARL9170_CMD_WREG_ASYNC = (CARL9170_CMD_WREG |
CARL9170_CMD_ASYNC_FLAG),
CARL9170_CMD_REBOOT_ASYNC = (CARL9170_CMD_REBOOT |
CARL9170_CMD_ASYNC_FLAG),
CARL9170_CMD_BCN_CTRL_ASYNC = (CARL9170_CMD_BCN_CTRL |
CARL9170_CMD_ASYNC_FLAG),
CARL9170_CMD_PSM_ASYNC = (CARL9170_CMD_PSM |
CARL9170_CMD_ASYNC_FLAG),
/* responses and traps */
CARL9170_RSP_FLAG = 0xc0,
CARL9170_RSP_PRETBTT = 0xc0,
CARL9170_RSP_TXCOMP = 0xc1,
CARL9170_RSP_BEACON_CONFIG = 0xc2,
CARL9170_RSP_ATIM = 0xc3,
CARL9170_RSP_WATCHDOG = 0xc6,
CARL9170_RSP_TEXT = 0xca,
CARL9170_RSP_HEXDUMP = 0xcc,
CARL9170_RSP_RADAR = 0xcd,
CARL9170_RSP_GPIO = 0xce,
CARL9170_RSP_BOOT = 0xcf,
};
struct carl9170_set_key_cmd {
__le16 user;
__le16 keyId;
__le16 type;
u8 macAddr[6];
u32 key[4];
} __packed __aligned(4);
#define CARL9170_SET_KEY_CMD_SIZE 28
struct carl9170_disable_key_cmd {
__le16 user;
__le16 padding;
} __packed __aligned(4);
#define CARL9170_DISABLE_KEY_CMD_SIZE 4
struct carl9170_u32_list {
u32 vals[0];
} __packed;
struct carl9170_reg_list {
__le32 regs[0];
} __packed;
struct carl9170_write_reg {
struct {
__le32 addr;
__le32 val;
} regs[0] __packed;
} __packed;
#define CARL9170FW_PHY_HT_ENABLE 0x4
#define CARL9170FW_PHY_HT_DYN2040 0x8
#define CARL9170FW_PHY_HT_EXT_CHAN_OFF 0x3
#define CARL9170FW_PHY_HT_EXT_CHAN_OFF_S 2
struct carl9170_rf_init {
__le32 freq;
u8 ht_settings;
u8 padding2[3];
__le32 delta_slope_coeff_exp;
__le32 delta_slope_coeff_man;
__le32 delta_slope_coeff_exp_shgi;
__le32 delta_slope_coeff_man_shgi;
__le32 finiteLoopCount;
} __packed;
#define CARL9170_RF_INIT_SIZE 28
struct carl9170_rf_init_result {
__le32 ret; /* AR9170_PHY_REG_AGC_CONTROL */
} __packed;
#define CARL9170_RF_INIT_RESULT_SIZE 4
#define CARL9170_PSM_SLEEP 0x1000
#define CARL9170_PSM_SOFTWARE 0
#define CARL9170_PSM_WAKE 0 /* internally used. */
#define CARL9170_PSM_COUNTER 0xfff
#define CARL9170_PSM_COUNTER_S 0
struct carl9170_psm {
__le32 state;
} __packed;
#define CARL9170_PSM_SIZE 4
struct carl9170_rx_filter_cmd {
__le32 rx_filter;
} __packed;
#define CARL9170_RX_FILTER_CMD_SIZE 4
#define CARL9170_RX_FILTER_BAD 0x01
#define CARL9170_RX_FILTER_OTHER_RA 0x02
#define CARL9170_RX_FILTER_DECRY_FAIL 0x04
#define CARL9170_RX_FILTER_CTL_OTHER 0x08
#define CARL9170_RX_FILTER_CTL_PSPOLL 0x10
#define CARL9170_RX_FILTER_CTL_BACKR 0x20
#define CARL9170_RX_FILTER_MGMT 0x40
#define CARL9170_RX_FILTER_DATA 0x80
#define CARL9170_RX_FILTER_EVERYTHING (~0)
struct carl9170_bcn_ctrl_cmd {
__le32 vif_id;
__le32 mode;
__le32 bcn_addr;
__le32 bcn_len;
} __packed;
#define CARL9170_BCN_CTRL_CMD_SIZE 16
#define CARL9170_BCN_CTRL_DRAIN 0
#define CARL9170_BCN_CTRL_CAB_TRIGGER 1
struct carl9170_wol_cmd {
__le32 flags;
u8 mac[6];
u8 bssid[6];
__le32 null_interval;
__le32 free_for_use2;
__le32 mask;
u8 pattern[32];
} __packed;
#define CARL9170_WOL_CMD_SIZE 60
#define CARL9170_WOL_DISCONNECT 1
#define CARL9170_WOL_MAGIC_PKT 2
struct carl9170_cmd_head {
union {
struct {
u8 len;
u8 cmd;
u8 seq;
u8 ext;
} __packed;
u32 hdr_data;
} __packed;
} __packed;
struct carl9170_cmd {
struct carl9170_cmd_head hdr;
union {
struct carl9170_set_key_cmd setkey;
struct carl9170_disable_key_cmd disablekey;
struct carl9170_u32_list echo;
struct carl9170_reg_list rreg;
struct carl9170_write_reg wreg;
struct carl9170_rf_init rf_init;
struct carl9170_psm psm;
struct carl9170_wol_cmd wol;
struct carl9170_bcn_ctrl_cmd bcn_ctrl;
struct carl9170_rx_filter_cmd rx_filter;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
} __packed __aligned(4);
#define CARL9170_TX_STATUS_QUEUE 3
#define CARL9170_TX_STATUS_QUEUE_S 0
#define CARL9170_TX_STATUS_RIX_S 2
#define CARL9170_TX_STATUS_RIX (3 << CARL9170_TX_STATUS_RIX_S)
#define CARL9170_TX_STATUS_TRIES_S 4
#define CARL9170_TX_STATUS_TRIES (7 << CARL9170_TX_STATUS_TRIES_S)
#define CARL9170_TX_STATUS_SUCCESS 0x80
#ifdef __CARL9170FW__
/*
* NOTE:
* Both structs [carl9170_tx_status and _carl9170_tx_status]
* need to be "bit for bit" in sync.
*/
struct carl9170_tx_status {
/*
* Beware of compiler bugs in all gcc pre 4.4!
*/
u8 cookie;
u8 queue:2;
u8 rix:2;
u8 tries:3;
u8 success:1;
} __packed;
#endif /* __CARL9170FW__ */
struct _carl9170_tx_status {
/*
* This version should be immune to all alignment bugs.
*/
u8 cookie;
u8 info;
} __packed;
#define CARL9170_TX_STATUS_SIZE 2
#define CARL9170_RSP_TX_STATUS_NUM (CARL9170_MAX_CMD_PAYLOAD_LEN / \
sizeof(struct _carl9170_tx_status))
#define CARL9170_TX_MAX_RATE_TRIES 7
#define CARL9170_TX_MAX_RATES 4
#define CARL9170_TX_MAX_RETRY_RATES (CARL9170_TX_MAX_RATES - 1)
#define CARL9170_ERR_MAGIC "ERR:"
#define CARL9170_BUG_MAGIC "BUG:"
struct carl9170_gpio {
__le32 gpio;
} __packed;
#define CARL9170_GPIO_SIZE 4
struct carl9170_tsf_rsp {
union {
__le32 tsf[2];
__le64 tsf_64;
} __packed;
} __packed;
#define CARL9170_TSF_RSP_SIZE 8
struct carl9170_tally_rsp {
__le32 active;
__le32 cca;
__le32 tx_time;
__le32 rx_total;
__le32 rx_overrun;
__le32 tick;
} __packed;
struct carl9170_rsp {
struct carl9170_cmd_head hdr;
union {
struct carl9170_rf_init_result rf_init_res;
struct carl9170_u32_list rreg_res;
struct carl9170_u32_list echo;
#ifdef __CARL9170FW__
struct carl9170_tx_status tx_status[0];
#endif /* __CARL9170FW__ */
struct _carl9170_tx_status _tx_status[0];
struct carl9170_gpio gpio;
struct carl9170_tsf_rsp tsf;
struct carl9170_psm psm;
struct carl9170_tally_rsp tally;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
} __packed __aligned(4);
#endif /* __CARL9170_SHARED_FWCMD_H */

View File

@@ -0,0 +1,277 @@
/*
* Shared CARL9170 Header
*
* Firmware descriptor format
*
* Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*/
#ifndef __CARL9170_SHARED_FWDESC_H
#define __CARL9170_SHARED_FWDESC_H
/* NOTE: Don't mess with the order of the flags! */
enum carl9170fw_feature_list {
/* Always set */
CARL9170FW_DUMMY_FEATURE,
/*
* Indicates that this image has special boot block which prevents
* legacy drivers to drive the firmware.
*/
CARL9170FW_MINIBOOT,
/* usb registers are initialized by the firmware */
CARL9170FW_USB_INIT_FIRMWARE,
/* command traps & notifications are send through EP2 */
CARL9170FW_USB_RESP_EP2,
/* usb download (app -> fw) stream */
CARL9170FW_USB_DOWN_STREAM,
/* usb upload (fw -> app) stream */
CARL9170FW_USB_UP_STREAM,
/* unusable - reserved to flag non-functional debug firmwares */
CARL9170FW_UNUSABLE,
/* AR9170_CMD_RF_INIT, AR9170_CMD_FREQ_START, AR9170_CMD_FREQUENCY */
CARL9170FW_COMMAND_PHY,
/* AR9170_CMD_EKEY, AR9170_CMD_DKEY */
CARL9170FW_COMMAND_CAM,
/* Firmware has a software Content After Beacon Queueing mechanism */
CARL9170FW_WLANTX_CAB,
/* The firmware is capable of responding to incoming BAR frames */
CARL9170FW_HANDLE_BACK_REQ,
/* GPIO Interrupt | CARL9170_RSP_GPIO */
CARL9170FW_GPIO_INTERRUPT,
/* Firmware PSM support | CARL9170_CMD_PSM */
CARL9170FW_PSM,
/* Firmware RX filter | CARL9170_CMD_RX_FILTER */
CARL9170FW_RX_FILTER,
/* Wake up on WLAN */
CARL9170FW_WOL,
/* Firmware supports PSM in the 5GHZ Band */
CARL9170FW_FIXED_5GHZ_PSM,
/* HW (ANI, CCA, MIB) tally counters */
CARL9170FW_HW_COUNTERS,
/* Firmware will pass BA when BARs are queued */
CARL9170FW_RX_BA_FILTER,
/* KEEP LAST */
__CARL9170FW_FEATURE_NUM
};
#define OTUS_MAGIC "OTAR"
#define MOTD_MAGIC "MOTD"
#define FIX_MAGIC "FIX\0"
#define DBG_MAGIC "DBG\0"
#define CHK_MAGIC "CHK\0"
#define TXSQ_MAGIC "TXSQ"
#define WOL_MAGIC "WOL\0"
#define LAST_MAGIC "LAST"
#define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
#define CARL9170FW_SET_MONTH(m) ((((m) - 1) % 12) * 31)
#define CARL9170FW_SET_YEAR(y) (((y) - 10) * 372)
#define CARL9170FW_GET_DAY(d) (((d) % 31) + 1)
#define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1)
#define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10)
#define CARL9170FW_MAGIC_SIZE 4
struct carl9170fw_desc_head {
u8 magic[CARL9170FW_MAGIC_SIZE];
__le16 length;
u8 min_ver;
u8 cur_ver;
} __packed;
#define CARL9170FW_DESC_HEAD_SIZE \
(sizeof(struct carl9170fw_desc_head))
#define CARL9170FW_OTUS_DESC_MIN_VER 6
#define CARL9170FW_OTUS_DESC_CUR_VER 7
struct carl9170fw_otus_desc {
struct carl9170fw_desc_head head;
__le32 feature_set;
__le32 fw_address;
__le32 bcn_addr;
__le16 bcn_len;
__le16 miniboot_size;
__le16 tx_frag_len;
__le16 rx_max_frame_len;
u8 tx_descs;
u8 cmd_bufs;
u8 api_ver;
u8 vif_num;
} __packed;
#define CARL9170FW_OTUS_DESC_SIZE \
(sizeof(struct carl9170fw_otus_desc))
#define CARL9170FW_MOTD_STRING_LEN 24
#define CARL9170FW_MOTD_RELEASE_LEN 20
#define CARL9170FW_MOTD_DESC_MIN_VER 1
#define CARL9170FW_MOTD_DESC_CUR_VER 2
struct carl9170fw_motd_desc {
struct carl9170fw_desc_head head;
__le32 fw_year_month_day;
char desc[CARL9170FW_MOTD_STRING_LEN];
char release[CARL9170FW_MOTD_RELEASE_LEN];
} __packed;
#define CARL9170FW_MOTD_DESC_SIZE \
(sizeof(struct carl9170fw_motd_desc))
#define CARL9170FW_FIX_DESC_MIN_VER 1
#define CARL9170FW_FIX_DESC_CUR_VER 2
struct carl9170fw_fix_entry {
__le32 address;
__le32 mask;
__le32 value;
} __packed;
struct carl9170fw_fix_desc {
struct carl9170fw_desc_head head;
struct carl9170fw_fix_entry data[0];
} __packed;
#define CARL9170FW_FIX_DESC_SIZE \
(sizeof(struct carl9170fw_fix_desc))
#define CARL9170FW_DBG_DESC_MIN_VER 1
#define CARL9170FW_DBG_DESC_CUR_VER 3
struct carl9170fw_dbg_desc {
struct carl9170fw_desc_head head;
__le32 bogoclock_addr;
__le32 counter_addr;
__le32 rx_total_addr;
__le32 rx_overrun_addr;
__le32 rx_filter;
/* Put your debugging definitions here */
} __packed;
#define CARL9170FW_DBG_DESC_SIZE \
(sizeof(struct carl9170fw_dbg_desc))
#define CARL9170FW_CHK_DESC_MIN_VER 1
#define CARL9170FW_CHK_DESC_CUR_VER 2
struct carl9170fw_chk_desc {
struct carl9170fw_desc_head head;
__le32 fw_crc32;
__le32 hdr_crc32;
} __packed;
#define CARL9170FW_CHK_DESC_SIZE \
(sizeof(struct carl9170fw_chk_desc))
#define CARL9170FW_TXSQ_DESC_MIN_VER 1
#define CARL9170FW_TXSQ_DESC_CUR_VER 1
struct carl9170fw_txsq_desc {
struct carl9170fw_desc_head head;
__le32 seq_table_addr;
} __packed;
#define CARL9170FW_TXSQ_DESC_SIZE \
(sizeof(struct carl9170fw_txsq_desc))
#define CARL9170FW_WOL_DESC_MIN_VER 1
#define CARL9170FW_WOL_DESC_CUR_VER 1
struct carl9170fw_wol_desc {
struct carl9170fw_desc_head head;
__le32 supported_triggers; /* CARL9170_WOL_ */
} __packed;
#define CARL9170FW_WOL_DESC_SIZE \
(sizeof(struct carl9170fw_wol_desc))
#define CARL9170FW_LAST_DESC_MIN_VER 1
#define CARL9170FW_LAST_DESC_CUR_VER 2
struct carl9170fw_last_desc {
struct carl9170fw_desc_head head;
} __packed;
#define CARL9170FW_LAST_DESC_SIZE \
(sizeof(struct carl9170fw_fix_desc))
#define CARL9170FW_DESC_MAX_LENGTH 8192
#define CARL9170FW_FILL_DESC(_magic, _length, _min_ver, _cur_ver) \
.head = { \
.magic = _magic, \
.length = cpu_to_le16(_length), \
.min_ver = _min_ver, \
.cur_ver = _cur_ver, \
}
static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head,
u8 magic[CARL9170FW_MAGIC_SIZE],
__le16 length, u8 min_ver, u8 cur_ver)
{
head->magic[0] = magic[0];
head->magic[1] = magic[1];
head->magic[2] = magic[2];
head->magic[3] = magic[3];
head->length = length;
head->min_ver = min_ver;
head->cur_ver = cur_ver;
}
#define carl9170fw_for_each_hdr(desc, fw_desc) \
for (desc = fw_desc; \
memcmp(desc->magic, LAST_MAGIC, CARL9170FW_MAGIC_SIZE) && \
le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE && \
le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH; \
desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length)))
#define CHECK_HDR_VERSION(head, _min_ver) \
(((head)->cur_ver < _min_ver) || ((head)->min_ver > _min_ver)) \
static inline bool carl9170fw_supports(__le32 list, u8 feature)
{
return le32_to_cpu(list) & BIT(feature);
}
static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head,
const u8 descid[CARL9170FW_MAGIC_SIZE],
u16 min_len, u8 compatible_revision)
{
if (descid[0] == head->magic[0] && descid[1] == head->magic[1] &&
descid[2] == head->magic[2] && descid[3] == head->magic[3] &&
!CHECK_HDR_VERSION(head, compatible_revision) &&
(le16_to_cpu(head->length) >= min_len))
return true;
return false;
}
#define CARL9170FW_MIN_SIZE 32
#define CARL9170FW_MAX_SIZE 16384
static inline bool carl9170fw_size_check(unsigned int len)
{
return (len <= CARL9170FW_MAX_SIZE && len >= CARL9170FW_MIN_SIZE);
}
#endif /* __CARL9170_SHARED_FWDESC_H */

View File

@@ -0,0 +1,817 @@
/*
* Shared Atheros AR9170 Header
*
* Register map, hardware-specific definitions
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#ifndef __CARL9170_SHARED_HW_H
#define __CARL9170_SHARED_HW_H
/* High Speed UART */
#define AR9170_UART_REG_BASE 0x1c0000
/* Definitions of interrupt registers */
#define AR9170_UART_REG_RX_BUFFER (AR9170_UART_REG_BASE + 0x000)
#define AR9170_UART_REG_TX_HOLDING (AR9170_UART_REG_BASE + 0x004)
#define AR9170_UART_REG_FIFO_CONTROL (AR9170_UART_REG_BASE + 0x010)
#define AR9170_UART_FIFO_CTRL_RESET_RX_FIFO 0x02
#define AR9170_UART_FIFO_CTRL_RESET_TX_FIFO 0x04
#define AR9170_UART_REG_LINE_CONTROL (AR9170_UART_REG_BASE + 0x014)
#define AR9170_UART_REG_MODEM_CONTROL (AR9170_UART_REG_BASE + 0x018)
#define AR9170_UART_MODEM_CTRL_DTR_BIT 0x01
#define AR9170_UART_MODEM_CTRL_RTS_BIT 0x02
#define AR9170_UART_MODEM_CTRL_INTERNAL_LOOP_BACK 0x10
#define AR9170_UART_MODEM_CTRL_AUTO_RTS 0x20
#define AR9170_UART_MODEM_CTRL_AUTO_CTR 0x40
#define AR9170_UART_REG_LINE_STATUS (AR9170_UART_REG_BASE + 0x01c)
#define AR9170_UART_LINE_STS_RX_DATA_READY 0x01
#define AR9170_UART_LINE_STS_RX_BUFFER_OVERRUN 0x02
#define AR9170_UART_LINE_STS_RX_BREAK_IND 0x10
#define AR9170_UART_LINE_STS_TX_FIFO_NEAR_EMPTY 0x20
#define AR9170_UART_LINE_STS_TRANSMITTER_EMPTY 0x40
#define AR9170_UART_REG_MODEM_STATUS (AR9170_UART_REG_BASE + 0x020)
#define AR9170_UART_MODEM_STS_CTS_CHANGE 0x01
#define AR9170_UART_MODEM_STS_DSR_CHANGE 0x02
#define AR9170_UART_MODEM_STS_DCD_CHANGE 0x08
#define AR9170_UART_MODEM_STS_CTS_COMPL 0x10
#define AR9170_UART_MODEM_STS_DSR_COMPL 0x20
#define AR9170_UART_MODEM_STS_DCD_COMPL 0x80
#define AR9170_UART_REG_SCRATCH (AR9170_UART_REG_BASE + 0x024)
#define AR9170_UART_REG_DIVISOR_LSB (AR9170_UART_REG_BASE + 0x028)
#define AR9170_UART_REG_DIVISOR_MSB (AR9170_UART_REG_BASE + 0x02c)
#define AR9170_UART_REG_WORD_RX_BUFFER (AR9170_UART_REG_BASE + 0x034)
#define AR9170_UART_REG_WORD_TX_HOLDING (AR9170_UART_REG_BASE + 0x038)
#define AR9170_UART_REG_FIFO_COUNT (AR9170_UART_REG_BASE + 0x03c)
#define AR9170_UART_REG_REMAINDER (AR9170_UART_REG_BASE + 0x04c)
/* Timer */
#define AR9170_TIMER_REG_BASE 0x1c1000
#define AR9170_TIMER_REG_WATCH_DOG (AR9170_TIMER_REG_BASE + 0x000)
#define AR9170_TIMER_REG_TIMER0 (AR9170_TIMER_REG_BASE + 0x010)
#define AR9170_TIMER_REG_TIMER1 (AR9170_TIMER_REG_BASE + 0x014)
#define AR9170_TIMER_REG_TIMER2 (AR9170_TIMER_REG_BASE + 0x018)
#define AR9170_TIMER_REG_TIMER3 (AR9170_TIMER_REG_BASE + 0x01c)
#define AR9170_TIMER_REG_TIMER4 (AR9170_TIMER_REG_BASE + 0x020)
#define AR9170_TIMER_REG_CONTROL (AR9170_TIMER_REG_BASE + 0x024)
#define AR9170_TIMER_CTRL_DISABLE_CLOCK 0x100
#define AR9170_TIMER_REG_INTERRUPT (AR9170_TIMER_REG_BASE + 0x028)
#define AR9170_TIMER_INT_TIMER0 0x001
#define AR9170_TIMER_INT_TIMER1 0x002
#define AR9170_TIMER_INT_TIMER2 0x004
#define AR9170_TIMER_INT_TIMER3 0x008
#define AR9170_TIMER_INT_TIMER4 0x010
#define AR9170_TIMER_INT_TICK_TIMER 0x100
#define AR9170_TIMER_REG_TICK_TIMER (AR9170_TIMER_REG_BASE + 0x030)
#define AR9170_TIMER_REG_CLOCK_LOW (AR9170_TIMER_REG_BASE + 0x040)
#define AR9170_TIMER_REG_CLOCK_HIGH (AR9170_TIMER_REG_BASE + 0x044)
#define AR9170_MAC_REG_BASE 0x1c3000
#define AR9170_MAC_REG_POWER_STATE_CTRL (AR9170_MAC_REG_BASE + 0x500)
#define AR9170_MAC_POWER_STATE_CTRL_RESET 0x20
#define AR9170_MAC_REG_MAC_POWER_STATE_CTRL (AR9170_MAC_REG_BASE + 0x50c)
#define AR9170_MAC_REG_INT_CTRL (AR9170_MAC_REG_BASE + 0x510)
#define AR9170_MAC_INT_TXC BIT(0)
#define AR9170_MAC_INT_RXC BIT(1)
#define AR9170_MAC_INT_RETRY_FAIL BIT(2)
#define AR9170_MAC_INT_WAKEUP BIT(3)
#define AR9170_MAC_INT_ATIM BIT(4)
#define AR9170_MAC_INT_DTIM BIT(5)
#define AR9170_MAC_INT_CFG_BCN BIT(6)
#define AR9170_MAC_INT_ABORT BIT(7)
#define AR9170_MAC_INT_QOS BIT(8)
#define AR9170_MAC_INT_MIMO_PS BIT(9)
#define AR9170_MAC_INT_KEY_GEN BIT(10)
#define AR9170_MAC_INT_DECRY_NOUSER BIT(11)
#define AR9170_MAC_INT_RADAR BIT(12)
#define AR9170_MAC_INT_QUIET_FRAME BIT(13)
#define AR9170_MAC_INT_PRETBTT BIT(14)
#define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514)
#define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518)
#define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51c)
#define AR9170_MAC_ATIM_PERIOD_S 0
#define AR9170_MAC_ATIM_PERIOD 0x0000ffff
#define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520)
#define AR9170_MAC_BCN_PERIOD_S 0
#define AR9170_MAC_BCN_PERIOD 0x0000ffff
#define AR9170_MAC_BCN_DTIM_S 16
#define AR9170_MAC_BCN_DTIM 0x00ff0000
#define AR9170_MAC_BCN_AP_MODE BIT(24)
#define AR9170_MAC_BCN_IBSS_MODE BIT(25)
#define AR9170_MAC_BCN_PWR_MGT BIT(26)
#define AR9170_MAC_BCN_STA_PS BIT(27)
#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524)
#define AR9170_MAC_PRETBTT_S 0
#define AR9170_MAC_PRETBTT 0x0000ffff
#define AR9170_MAC_PRETBTT2_S 16
#define AR9170_MAC_PRETBTT2 0xffff0000
#define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610)
#define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614)
#define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618)
#define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c)
#define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624)
#define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628)
#define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62c)
#define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630)
#define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634)
#define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638)
#define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c)
#define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640)
#define AR9170_MAC_REG_AFTER_PNP (AR9170_MAC_REG_BASE + 0x648)
#define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64c)
#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658)
#define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674)
#define AR9170_MAC_SNIFFER_ENABLE_PROMISC BIT(0)
#define AR9170_MAC_SNIFFER_DEFAULTS 0x02000000
#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678)
#define AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE BIT(2)
#define AR9170_MAC_ENCRYPTION_RX_SOFTWARE BIT(3)
#define AR9170_MAC_ENCRYPTION_DEFAULTS 0x70
#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680)
#define AR9170_MAC_REG_MISC_684 (AR9170_MAC_REG_BASE + 0x684)
#define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688)
#define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c)
#define AR9170_MAC_FTF_ASSOC_REQ BIT(0)
#define AR9170_MAC_FTF_ASSOC_RESP BIT(1)
#define AR9170_MAC_FTF_REASSOC_REQ BIT(2)
#define AR9170_MAC_FTF_REASSOC_RESP BIT(3)
#define AR9170_MAC_FTF_PRB_REQ BIT(4)
#define AR9170_MAC_FTF_PRB_RESP BIT(5)
#define AR9170_MAC_FTF_BIT6 BIT(6)
#define AR9170_MAC_FTF_BIT7 BIT(7)
#define AR9170_MAC_FTF_BEACON BIT(8)
#define AR9170_MAC_FTF_ATIM BIT(9)
#define AR9170_MAC_FTF_DEASSOC BIT(10)
#define AR9170_MAC_FTF_AUTH BIT(11)
#define AR9170_MAC_FTF_DEAUTH BIT(12)
#define AR9170_MAC_FTF_BIT13 BIT(13)
#define AR9170_MAC_FTF_BIT14 BIT(14)
#define AR9170_MAC_FTF_BIT15 BIT(15)
#define AR9170_MAC_FTF_BAR BIT(24)
#define AR9170_MAC_FTF_BA BIT(25)
#define AR9170_MAC_FTF_PSPOLL BIT(26)
#define AR9170_MAC_FTF_RTS BIT(27)
#define AR9170_MAC_FTF_CTS BIT(28)
#define AR9170_MAC_FTF_ACK BIT(29)
#define AR9170_MAC_FTF_CFE BIT(30)
#define AR9170_MAC_FTF_CFE_ACK BIT(31)
#define AR9170_MAC_FTF_DEFAULTS 0x0500ffff
#define AR9170_MAC_FTF_MONITOR 0xff00ffff
#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690)
#define AR9170_MAC_REG_ACK_TPC (AR9170_MAC_REG_BASE + 0x694)
#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698)
#define AR9170_MAC_REG_RX_TIMEOUT_COUNT (AR9170_MAC_REG_BASE + 0x69c)
#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6a0)
#define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6a4)
#define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6a8)
#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6ac)
#define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6b0)
#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6bc)
#define AR9170_MAC_REG_TX_BLOCKACKS (AR9170_MAC_REG_BASE + 0x6c0)
#define AR9170_MAC_REG_NAV_COUNT (AR9170_MAC_REG_BASE + 0x6c4)
#define AR9170_MAC_REG_BACKOFF_STATUS (AR9170_MAC_REG_BASE + 0x6c8)
#define AR9170_MAC_BACKOFF_CCA BIT(24)
#define AR9170_MAC_BACKOFF_TX_PEX BIT(25)
#define AR9170_MAC_BACKOFF_RX_PE BIT(26)
#define AR9170_MAC_BACKOFF_MD_READY BIT(27)
#define AR9170_MAC_BACKOFF_TX_PE BIT(28)
#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6cc)
#define AR9170_MAC_REG_TX_COMPLETE (AR9170_MAC_REG_BASE + 0x6d4)
#define AR9170_MAC_REG_CHANNEL_BUSY (AR9170_MAC_REG_BASE + 0x6e8)
#define AR9170_MAC_REG_EXT_BUSY (AR9170_MAC_REG_BASE + 0x6ec)
#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6f0)
#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6f4)
#define AR9170_MAC_REG_ACK_FC (AR9170_MAC_REG_BASE + 0x6f8)
#define AR9170_MAC_REG_CAM_MODE (AR9170_MAC_REG_BASE + 0x700)
#define AR9170_MAC_CAM_IBSS 0xe0
#define AR9170_MAC_CAM_AP 0xa1
#define AR9170_MAC_CAM_STA 0x2
#define AR9170_MAC_CAM_AP_WDS 0x3
#define AR9170_MAC_CAM_DEFAULTS (0xf << 24)
#define AR9170_MAC_CAM_HOST_PENDING 0x80000000
#define AR9170_MAC_REG_CAM_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704)
#define AR9170_MAC_REG_CAM_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708)
#define AR9170_MAC_REG_CAM_ADDR (AR9170_MAC_REG_BASE + 0x70c)
#define AR9170_MAC_CAM_ADDR_WRITE 0x80000000
#define AR9170_MAC_REG_CAM_DATA0 (AR9170_MAC_REG_BASE + 0x720)
#define AR9170_MAC_REG_CAM_DATA1 (AR9170_MAC_REG_BASE + 0x724)
#define AR9170_MAC_REG_CAM_DATA2 (AR9170_MAC_REG_BASE + 0x728)
#define AR9170_MAC_REG_CAM_DATA3 (AR9170_MAC_REG_BASE + 0x72c)
#define AR9170_MAC_REG_CAM_DBG0 (AR9170_MAC_REG_BASE + 0x730)
#define AR9170_MAC_REG_CAM_DBG1 (AR9170_MAC_REG_BASE + 0x734)
#define AR9170_MAC_REG_CAM_DBG2 (AR9170_MAC_REG_BASE + 0x738)
#define AR9170_MAC_REG_CAM_STATE (AR9170_MAC_REG_BASE + 0x73c)
#define AR9170_MAC_CAM_STATE_READ_PENDING 0x40000000
#define AR9170_MAC_CAM_STATE_WRITE_PENDING 0x80000000
#define AR9170_MAC_REG_CAM_TXKEY (AR9170_MAC_REG_BASE + 0x740)
#define AR9170_MAC_REG_CAM_RXKEY (AR9170_MAC_REG_BASE + 0x750)
#define AR9170_MAC_REG_CAM_TX_ENC_TYPE (AR9170_MAC_REG_BASE + 0x760)
#define AR9170_MAC_REG_CAM_RX_ENC_TYPE (AR9170_MAC_REG_BASE + 0x770)
#define AR9170_MAC_REG_CAM_TX_SERACH_HIT (AR9170_MAC_REG_BASE + 0x780)
#define AR9170_MAC_REG_CAM_RX_SERACH_HIT (AR9170_MAC_REG_BASE + 0x790)
#define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xb00)
#define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xb04)
#define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xb08)
#define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xb0c)
#define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xb10)
#define AR9170_MAC_REG_AC2_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xb14)
#define AR9170_MAC_REG_AC4_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xb18)
#define AR9170_MAC_REG_TXOP_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0xb1c)
#define AR9170_MAC_REG_TXOP_ACK_INTERVAL (AR9170_MAC_REG_BASE + 0xb20)
#define AR9170_MAC_REG_CONTENTION_POINT (AR9170_MAC_REG_BASE + 0xb24)
#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xb28)
#define AR9170_MAC_REG_TID_CFACK_CFEND_RATE (AR9170_MAC_REG_BASE + 0xb2c)
#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xb30)
#define AR9170_MAC_REG_TKIP_TSC (AR9170_MAC_REG_BASE + 0xb34)
#define AR9170_MAC_REG_TXOP_DURATION (AR9170_MAC_REG_BASE + 0xb38)
#define AR9170_MAC_REG_TX_QOS_THRESHOLD (AR9170_MAC_REG_BASE + 0xb3c)
#define AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA (AR9170_MAC_REG_BASE + 0xb40)
#define AR9170_MAC_VIRTUAL_CCA_Q0 BIT(15)
#define AR9170_MAC_VIRTUAL_CCA_Q1 BIT(16)
#define AR9170_MAC_VIRTUAL_CCA_Q2 BIT(17)
#define AR9170_MAC_VIRTUAL_CCA_Q3 BIT(18)
#define AR9170_MAC_VIRTUAL_CCA_Q4 BIT(19)
#define AR9170_MAC_VIRTUAL_CCA_ALL (0xf8000)
#define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xb44)
#define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xb48)
#define AR9170_MAC_REG_AMPDU_COUNT (AR9170_MAC_REG_BASE + 0xb88)
#define AR9170_MAC_REG_MPDU_COUNT (AR9170_MAC_REG_BASE + 0xb8c)
#define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xb9c)
#define AR9170_MAC_AMPDU_FACTOR 0x7f0000
#define AR9170_MAC_AMPDU_FACTOR_S 16
#define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xba0)
#define AR9170_MAC_AMPDU_DENSITY 0x7
#define AR9170_MAC_AMPDU_DENSITY_S 0
#define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xbb0)
#define AR9170_MAC_FCS_SWFCS 0x1
#define AR9170_MAC_FCS_FIFO_PROT 0x4
#define AR9170_MAC_REG_RTS_CTS_TPC (AR9170_MAC_REG_BASE + 0xbb4)
#define AR9170_MAC_REG_CFEND_QOSNULL_TPC (AR9170_MAC_REG_BASE + 0xbb8)
#define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xc00)
#define AR9170_MAC_REG_RX_CONTROL (AR9170_MAC_REG_BASE + 0xc40)
#define AR9170_MAC_RX_CTRL_DEAGG 0x1
#define AR9170_MAC_RX_CTRL_SHORT_FILTER 0x2
#define AR9170_MAC_RX_CTRL_SA_DA_SEARCH 0x20
#define AR9170_MAC_RX_CTRL_PASS_TO_HOST BIT(28)
#define AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER BIT(30)
#define AR9170_MAC_REG_RX_CONTROL_1 (AR9170_MAC_REG_BASE + 0xc44)
#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xc50)
#define AR9170_MAC_REG_RX_MPDU (AR9170_MAC_REG_BASE + 0xca0)
#define AR9170_MAC_REG_RX_DROPPED_MPDU (AR9170_MAC_REG_BASE + 0xca4)
#define AR9170_MAC_REG_RX_DEL_MPDU (AR9170_MAC_REG_BASE + 0xca8)
#define AR9170_MAC_REG_RX_PHY_MISC_ERROR (AR9170_MAC_REG_BASE + 0xcac)
#define AR9170_MAC_REG_RX_PHY_XR_ERROR (AR9170_MAC_REG_BASE + 0xcb0)
#define AR9170_MAC_REG_RX_PHY_OFDM_ERROR (AR9170_MAC_REG_BASE + 0xcb4)
#define AR9170_MAC_REG_RX_PHY_CCK_ERROR (AR9170_MAC_REG_BASE + 0xcb8)
#define AR9170_MAC_REG_RX_PHY_HT_ERROR (AR9170_MAC_REG_BASE + 0xcbc)
#define AR9170_MAC_REG_RX_PHY_TOTAL (AR9170_MAC_REG_BASE + 0xcc0)
#define AR9170_MAC_REG_DMA_TXQ_ADDR (AR9170_MAC_REG_BASE + 0xd00)
#define AR9170_MAC_REG_DMA_TXQ_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd04)
#define AR9170_MAC_REG_DMA_TXQ0_ADDR (AR9170_MAC_REG_BASE + 0xd00)
#define AR9170_MAC_REG_DMA_TXQ0_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd04)
#define AR9170_MAC_REG_DMA_TXQ1_ADDR (AR9170_MAC_REG_BASE + 0xd08)
#define AR9170_MAC_REG_DMA_TXQ1_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd0c)
#define AR9170_MAC_REG_DMA_TXQ2_ADDR (AR9170_MAC_REG_BASE + 0xd10)
#define AR9170_MAC_REG_DMA_TXQ2_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd14)
#define AR9170_MAC_REG_DMA_TXQ3_ADDR (AR9170_MAC_REG_BASE + 0xd18)
#define AR9170_MAC_REG_DMA_TXQ3_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd1c)
#define AR9170_MAC_REG_DMA_TXQ4_ADDR (AR9170_MAC_REG_BASE + 0xd20)
#define AR9170_MAC_REG_DMA_TXQ4_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd24)
#define AR9170_MAC_REG_DMA_RXQ_ADDR (AR9170_MAC_REG_BASE + 0xd28)
#define AR9170_MAC_REG_DMA_RXQ_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd2c)
#define AR9170_MAC_REG_DMA_TRIGGER (AR9170_MAC_REG_BASE + 0xd30)
#define AR9170_DMA_TRIGGER_TXQ0 BIT(0)
#define AR9170_DMA_TRIGGER_TXQ1 BIT(1)
#define AR9170_DMA_TRIGGER_TXQ2 BIT(2)
#define AR9170_DMA_TRIGGER_TXQ3 BIT(3)
#define AR9170_DMA_TRIGGER_TXQ4 BIT(4)
#define AR9170_DMA_TRIGGER_RXQ BIT(8)
#define AR9170_MAC_REG_DMA_WLAN_STATUS (AR9170_MAC_REG_BASE + 0xd38)
#define AR9170_MAC_REG_DMA_STATUS (AR9170_MAC_REG_BASE + 0xd3c)
#define AR9170_MAC_REG_DMA_TXQ_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd40)
#define AR9170_MAC_REG_DMA_TXQ0_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd40)
#define AR9170_MAC_REG_DMA_TXQ1_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd44)
#define AR9170_MAC_REG_DMA_TXQ2_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd48)
#define AR9170_MAC_REG_DMA_TXQ3_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd4c)
#define AR9170_MAC_REG_DMA_TXQ4_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd50)
#define AR9170_MAC_REG_DMA_TXQ0Q1_LEN (AR9170_MAC_REG_BASE + 0xd54)
#define AR9170_MAC_REG_DMA_TXQ2Q3_LEN (AR9170_MAC_REG_BASE + 0xd58)
#define AR9170_MAC_REG_DMA_TXQ4_LEN (AR9170_MAC_REG_BASE + 0xd5c)
#define AR9170_MAC_REG_DMA_TXQX_LAST_ADDR (AR9170_MAC_REG_BASE + 0xd74)
#define AR9170_MAC_REG_DMA_TXQX_FAIL_ADDR (AR9170_MAC_REG_BASE + 0xd78)
#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xd7c)
#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f
#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0
#define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000
#define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000
#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xd84)
#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xd88)
#define AR9170_MAC_BCN_LENGTH_MAX 256
#define AR9170_MAC_REG_BCN_STATUS (AR9170_MAC_REG_BASE + 0xd8c)
#define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xd90)
#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xd94)
#define AR9170_BCN_CTRL_READY 0x01
#define AR9170_BCN_CTRL_LOCK 0x02
#define AR9170_MAC_REG_BCN_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd98)
#define AR9170_MAC_REG_BCN_COUNT (AR9170_MAC_REG_BASE + 0xd9c)
#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xda0)
#define AR9170_MAC_BCN_HT1_HT_EN BIT(0)
#define AR9170_MAC_BCN_HT1_GF_PMB BIT(1)
#define AR9170_MAC_BCN_HT1_SP_EXP BIT(2)
#define AR9170_MAC_BCN_HT1_TX_BF BIT(3)
#define AR9170_MAC_BCN_HT1_PWR_CTRL_S 4
#define AR9170_MAC_BCN_HT1_PWR_CTRL 0x70
#define AR9170_MAC_BCN_HT1_TX_ANT1 BIT(7)
#define AR9170_MAC_BCN_HT1_TX_ANT0 BIT(8)
#define AR9170_MAC_BCN_HT1_NUM_LFT_S 9
#define AR9170_MAC_BCN_HT1_NUM_LFT 0x600
#define AR9170_MAC_BCN_HT1_BWC_20M_EXT BIT(16)
#define AR9170_MAC_BCN_HT1_BWC_40M_SHARED BIT(17)
#define AR9170_MAC_BCN_HT1_BWC_40M_DUP (BIT(16) | BIT(17))
#define AR9170_MAC_BCN_HT1_BF_MCS_S 18
#define AR9170_MAC_BCN_HT1_BF_MCS 0x1c0000
#define AR9170_MAC_BCN_HT1_TPC_S 21
#define AR9170_MAC_BCN_HT1_TPC 0x7e00000
#define AR9170_MAC_BCN_HT1_CHAIN_MASK_S 27
#define AR9170_MAC_BCN_HT1_CHAIN_MASK 0x38000000
#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xda4)
#define AR9170_MAC_BCN_HT2_MCS_S 0
#define AR9170_MAC_BCN_HT2_MCS 0x7f
#define AR9170_MAC_BCN_HT2_BW40 BIT(8)
#define AR9170_MAC_BCN_HT2_SMOOTHING BIT(9)
#define AR9170_MAC_BCN_HT2_SS BIT(10)
#define AR9170_MAC_BCN_HT2_NSS BIT(11)
#define AR9170_MAC_BCN_HT2_STBC_S 12
#define AR9170_MAC_BCN_HT2_STBC 0x3000
#define AR9170_MAC_BCN_HT2_ADV_COD BIT(14)
#define AR9170_MAC_BCN_HT2_SGI BIT(15)
#define AR9170_MAC_BCN_HT2_LEN_S 16
#define AR9170_MAC_BCN_HT2_LEN 0xffff0000
#define AR9170_MAC_REG_DMA_TXQX_ADDR_CURR (AR9170_MAC_REG_BASE + 0xdc0)
/* Random number generator */
#define AR9170_RAND_REG_BASE 0x1d0000
#define AR9170_RAND_REG_NUM (AR9170_RAND_REG_BASE + 0x000)
#define AR9170_RAND_REG_MODE (AR9170_RAND_REG_BASE + 0x004)
#define AR9170_RAND_MODE_MANUAL 0x000
#define AR9170_RAND_MODE_FREE 0x001
/* GPIO */
#define AR9170_GPIO_REG_BASE 0x1d0100
#define AR9170_GPIO_REG_PORT_TYPE (AR9170_GPIO_REG_BASE + 0x000)
#define AR9170_GPIO_REG_PORT_DATA (AR9170_GPIO_REG_BASE + 0x004)
#define AR9170_GPIO_PORT_LED_0 1
#define AR9170_GPIO_PORT_LED_1 2
/* WPS Button GPIO for TP-Link TL-WN821N */
#define AR9170_GPIO_PORT_WPS_BUTTON_PRESSED 4
/* Memory Controller */
#define AR9170_MC_REG_BASE 0x1d1000
#define AR9170_MC_REG_FLASH_WAIT_STATE (AR9170_MC_REG_BASE + 0x000)
#define AR9170_MC_REG_SEEPROM_WP0 (AR9170_MC_REG_BASE + 0x400)
#define AR9170_MC_REG_SEEPROM_WP1 (AR9170_MC_REG_BASE + 0x404)
#define AR9170_MC_REG_SEEPROM_WP2 (AR9170_MC_REG_BASE + 0x408)
/* Interrupt Controller */
#define AR9170_MAX_INT_SRC 9
#define AR9170_INT_REG_BASE 0x1d2000
#define AR9170_INT_REG_FLAG (AR9170_INT_REG_BASE + 0x000)
#define AR9170_INT_REG_FIQ_MASK (AR9170_INT_REG_BASE + 0x004)
#define AR9170_INT_REG_IRQ_MASK (AR9170_INT_REG_BASE + 0x008)
/* INT_REG_FLAG, INT_REG_FIQ_MASK and INT_REG_IRQ_MASK */
#define AR9170_INT_FLAG_WLAN 0x001
#define AR9170_INT_FLAG_PTAB_BIT 0x002
#define AR9170_INT_FLAG_SE_BIT 0x004
#define AR9170_INT_FLAG_UART_BIT 0x008
#define AR9170_INT_FLAG_TIMER_BIT 0x010
#define AR9170_INT_FLAG_EXT_BIT 0x020
#define AR9170_INT_FLAG_SW_BIT 0x040
#define AR9170_INT_FLAG_USB_BIT 0x080
#define AR9170_INT_FLAG_ETHERNET_BIT 0x100
#define AR9170_INT_REG_PRIORITY1 (AR9170_INT_REG_BASE + 0x00c)
#define AR9170_INT_REG_PRIORITY2 (AR9170_INT_REG_BASE + 0x010)
#define AR9170_INT_REG_PRIORITY3 (AR9170_INT_REG_BASE + 0x014)
#define AR9170_INT_REG_EXT_INT_CONTROL (AR9170_INT_REG_BASE + 0x018)
#define AR9170_INT_REG_SW_INT_CONTROL (AR9170_INT_REG_BASE + 0x01c)
#define AR9170_INT_SW_INT_ENABLE 0x1
#define AR9170_INT_REG_FIQ_ENCODE (AR9170_INT_REG_BASE + 0x020)
#define AR9170_INT_INT_IRQ_ENCODE (AR9170_INT_REG_BASE + 0x024)
/* Power Management */
#define AR9170_PWR_REG_BASE 0x1d4000
#define AR9170_PWR_REG_POWER_STATE (AR9170_PWR_REG_BASE + 0x000)
#define AR9170_PWR_REG_RESET (AR9170_PWR_REG_BASE + 0x004)
#define AR9170_PWR_RESET_COMMIT_RESET_MASK BIT(0)
#define AR9170_PWR_RESET_WLAN_MASK BIT(1)
#define AR9170_PWR_RESET_DMA_MASK BIT(2)
#define AR9170_PWR_RESET_BRIDGE_MASK BIT(3)
#define AR9170_PWR_RESET_AHB_MASK BIT(9)
#define AR9170_PWR_RESET_BB_WARM_RESET BIT(10)
#define AR9170_PWR_RESET_BB_COLD_RESET BIT(11)
#define AR9170_PWR_RESET_ADDA_CLK_COLD_RESET BIT(12)
#define AR9170_PWR_RESET_PLL BIT(13)
#define AR9170_PWR_RESET_USB_PLL BIT(14)
#define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008)
#define AR9170_PWR_CLK_AHB_40MHZ 0
#define AR9170_PWR_CLK_AHB_20_22MHZ 1
#define AR9170_PWR_CLK_AHB_40_44MHZ 2
#define AR9170_PWR_CLK_AHB_80_88MHZ 3
#define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70
#define AR9170_PWR_REG_CHIP_REVISION (AR9170_PWR_REG_BASE + 0x010)
#define AR9170_PWR_REG_PLL_ADDAC (AR9170_PWR_REG_BASE + 0x014)
#define AR9170_PWR_PLL_ADDAC_DIV_S 2
#define AR9170_PWR_PLL_ADDAC_DIV 0xffc
#define AR9170_PWR_REG_WATCH_DOG_MAGIC (AR9170_PWR_REG_BASE + 0x020)
/* Faraday USB Controller */
#define AR9170_USB_REG_BASE 0x1e1000
#define AR9170_USB_REG_MAIN_CTRL (AR9170_USB_REG_BASE + 0x000)
#define AR9170_USB_MAIN_CTRL_REMOTE_WAKEUP BIT(0)
#define AR9170_USB_MAIN_CTRL_ENABLE_GLOBAL_INT BIT(2)
#define AR9170_USB_MAIN_CTRL_GO_TO_SUSPEND BIT(3)
#define AR9170_USB_MAIN_CTRL_RESET BIT(4)
#define AR9170_USB_MAIN_CTRL_CHIP_ENABLE BIT(5)
#define AR9170_USB_MAIN_CTRL_HIGHSPEED BIT(6)
#define AR9170_USB_REG_DEVICE_ADDRESS (AR9170_USB_REG_BASE + 0x001)
#define AR9170_USB_DEVICE_ADDRESS_CONFIGURE BIT(7)
#define AR9170_USB_REG_TEST (AR9170_USB_REG_BASE + 0x002)
#define AR9170_USB_REG_PHY_TEST_SELECT (AR9170_USB_REG_BASE + 0x008)
#define AR9170_USB_REG_CX_CONFIG_STATUS (AR9170_USB_REG_BASE + 0x00b)
#define AR9170_USB_REG_EP0_DATA (AR9170_USB_REG_BASE + 0x00c)
#define AR9170_USB_REG_EP0_DATA1 (AR9170_USB_REG_BASE + 0x00c)
#define AR9170_USB_REG_EP0_DATA2 (AR9170_USB_REG_BASE + 0x00d)
#define AR9170_USB_REG_INTR_MASK_BYTE_0 (AR9170_USB_REG_BASE + 0x011)
#define AR9170_USB_REG_INTR_MASK_BYTE_1 (AR9170_USB_REG_BASE + 0x012)
#define AR9170_USB_REG_INTR_MASK_BYTE_2 (AR9170_USB_REG_BASE + 0x013)
#define AR9170_USB_REG_INTR_MASK_BYTE_3 (AR9170_USB_REG_BASE + 0x014)
#define AR9170_USB_REG_INTR_MASK_BYTE_4 (AR9170_USB_REG_BASE + 0x015)
#define AR9170_USB_INTR_DISABLE_OUT_INT (BIT(7) | BIT(6))
#define AR9170_USB_REG_INTR_MASK_BYTE_5 (AR9170_USB_REG_BASE + 0x016)
#define AR9170_USB_REG_INTR_MASK_BYTE_6 (AR9170_USB_REG_BASE + 0x017)
#define AR9170_USB_INTR_DISABLE_IN_INT BIT(6)
#define AR9170_USB_REG_INTR_MASK_BYTE_7 (AR9170_USB_REG_BASE + 0x018)
#define AR9170_USB_REG_INTR_GROUP (AR9170_USB_REG_BASE + 0x020)
#define AR9170_USB_REG_INTR_SOURCE_0 (AR9170_USB_REG_BASE + 0x021)
#define AR9170_USB_INTR_SRC0_SETUP BIT(0)
#define AR9170_USB_INTR_SRC0_IN BIT(1)
#define AR9170_USB_INTR_SRC0_OUT BIT(2)
#define AR9170_USB_INTR_SRC0_FAIL BIT(3) /* ??? */
#define AR9170_USB_INTR_SRC0_END BIT(4) /* ??? */
#define AR9170_USB_INTR_SRC0_ABORT BIT(7)
#define AR9170_USB_REG_INTR_SOURCE_1 (AR9170_USB_REG_BASE + 0x022)
#define AR9170_USB_REG_INTR_SOURCE_2 (AR9170_USB_REG_BASE + 0x023)
#define AR9170_USB_REG_INTR_SOURCE_3 (AR9170_USB_REG_BASE + 0x024)
#define AR9170_USB_REG_INTR_SOURCE_4 (AR9170_USB_REG_BASE + 0x025)
#define AR9170_USB_REG_INTR_SOURCE_5 (AR9170_USB_REG_BASE + 0x026)
#define AR9170_USB_REG_INTR_SOURCE_6 (AR9170_USB_REG_BASE + 0x027)
#define AR9170_USB_REG_INTR_SOURCE_7 (AR9170_USB_REG_BASE + 0x028)
#define AR9170_USB_INTR_SRC7_USB_RESET BIT(1)
#define AR9170_USB_INTR_SRC7_USB_SUSPEND BIT(2)
#define AR9170_USB_INTR_SRC7_USB_RESUME BIT(3)
#define AR9170_USB_INTR_SRC7_ISO_SEQ_ERR BIT(4)
#define AR9170_USB_INTR_SRC7_ISO_SEQ_ABORT BIT(5)
#define AR9170_USB_INTR_SRC7_TX0BYTE BIT(6)
#define AR9170_USB_INTR_SRC7_RX0BYTE BIT(7)
#define AR9170_USB_REG_IDLE_COUNT (AR9170_USB_REG_BASE + 0x02f)
#define AR9170_USB_REG_EP_MAP (AR9170_USB_REG_BASE + 0x030)
#define AR9170_USB_REG_EP1_MAP (AR9170_USB_REG_BASE + 0x030)
#define AR9170_USB_REG_EP2_MAP (AR9170_USB_REG_BASE + 0x031)
#define AR9170_USB_REG_EP3_MAP (AR9170_USB_REG_BASE + 0x032)
#define AR9170_USB_REG_EP4_MAP (AR9170_USB_REG_BASE + 0x033)
#define AR9170_USB_REG_EP5_MAP (AR9170_USB_REG_BASE + 0x034)
#define AR9170_USB_REG_EP6_MAP (AR9170_USB_REG_BASE + 0x035)
#define AR9170_USB_REG_EP7_MAP (AR9170_USB_REG_BASE + 0x036)
#define AR9170_USB_REG_EP8_MAP (AR9170_USB_REG_BASE + 0x037)
#define AR9170_USB_REG_EP9_MAP (AR9170_USB_REG_BASE + 0x038)
#define AR9170_USB_REG_EP10_MAP (AR9170_USB_REG_BASE + 0x039)
#define AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x03f)
#define AR9170_USB_EP_IN_TOGGLE 0x10
#define AR9170_USB_REG_EP_IN_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x03e)
#define AR9170_USB_REG_EP_OUT_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x05f)
#define AR9170_USB_EP_OUT_TOGGLE 0x10
#define AR9170_USB_REG_EP_OUT_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x05e)
#define AR9170_USB_REG_EP3_BYTE_COUNT_HIGH (AR9170_USB_REG_BASE + 0x0ae)
#define AR9170_USB_REG_EP3_BYTE_COUNT_LOW (AR9170_USB_REG_BASE + 0x0be)
#define AR9170_USB_REG_EP4_BYTE_COUNT_HIGH (AR9170_USB_REG_BASE + 0x0af)
#define AR9170_USB_REG_EP4_BYTE_COUNT_LOW (AR9170_USB_REG_BASE + 0x0bf)
#define AR9170_USB_REG_FIFO_MAP (AR9170_USB_REG_BASE + 0x080)
#define AR9170_USB_REG_FIFO0_MAP (AR9170_USB_REG_BASE + 0x080)
#define AR9170_USB_REG_FIFO1_MAP (AR9170_USB_REG_BASE + 0x081)
#define AR9170_USB_REG_FIFO2_MAP (AR9170_USB_REG_BASE + 0x082)
#define AR9170_USB_REG_FIFO3_MAP (AR9170_USB_REG_BASE + 0x083)
#define AR9170_USB_REG_FIFO4_MAP (AR9170_USB_REG_BASE + 0x084)
#define AR9170_USB_REG_FIFO5_MAP (AR9170_USB_REG_BASE + 0x085)
#define AR9170_USB_REG_FIFO6_MAP (AR9170_USB_REG_BASE + 0x086)
#define AR9170_USB_REG_FIFO7_MAP (AR9170_USB_REG_BASE + 0x087)
#define AR9170_USB_REG_FIFO8_MAP (AR9170_USB_REG_BASE + 0x088)
#define AR9170_USB_REG_FIFO9_MAP (AR9170_USB_REG_BASE + 0x089)
#define AR9170_USB_REG_FIFO_CONFIG (AR9170_USB_REG_BASE + 0x090)
#define AR9170_USB_REG_FIFO0_CONFIG (AR9170_USB_REG_BASE + 0x090)
#define AR9170_USB_REG_FIFO1_CONFIG (AR9170_USB_REG_BASE + 0x091)
#define AR9170_USB_REG_FIFO2_CONFIG (AR9170_USB_REG_BASE + 0x092)
#define AR9170_USB_REG_FIFO3_CONFIG (AR9170_USB_REG_BASE + 0x093)
#define AR9170_USB_REG_FIFO4_CONFIG (AR9170_USB_REG_BASE + 0x094)
#define AR9170_USB_REG_FIFO5_CONFIG (AR9170_USB_REG_BASE + 0x095)
#define AR9170_USB_REG_FIFO6_CONFIG (AR9170_USB_REG_BASE + 0x096)
#define AR9170_USB_REG_FIFO7_CONFIG (AR9170_USB_REG_BASE + 0x097)
#define AR9170_USB_REG_FIFO8_CONFIG (AR9170_USB_REG_BASE + 0x098)
#define AR9170_USB_REG_FIFO9_CONFIG (AR9170_USB_REG_BASE + 0x099)
#define AR9170_USB_REG_EP3_DATA (AR9170_USB_REG_BASE + 0x0f8)
#define AR9170_USB_REG_EP4_DATA (AR9170_USB_REG_BASE + 0x0fc)
#define AR9170_USB_REG_FIFO_SIZE (AR9170_USB_REG_BASE + 0x100)
#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108)
#define AR9170_USB_DMA_CTL_ENABLE_TO_DEVICE BIT(0)
#define AR9170_USB_DMA_CTL_ENABLE_FROM_DEVICE BIT(1)
#define AR9170_USB_DMA_CTL_HIGH_SPEED BIT(2)
#define AR9170_USB_DMA_CTL_UP_PACKET_MODE BIT(3)
#define AR9170_USB_DMA_CTL_UP_STREAM_S 4
#define AR9170_USB_DMA_CTL_UP_STREAM (BIT(4) | BIT(5))
#define AR9170_USB_DMA_CTL_UP_STREAM_4K (0)
#define AR9170_USB_DMA_CTL_UP_STREAM_8K BIT(4)
#define AR9170_USB_DMA_CTL_UP_STREAM_16K BIT(5)
#define AR9170_USB_DMA_CTL_UP_STREAM_32K (BIT(4) | BIT(5))
#define AR9170_USB_DMA_CTL_DOWN_STREAM BIT(6)
#define AR9170_USB_REG_DMA_STATUS (AR9170_USB_REG_BASE + 0x10c)
#define AR9170_USB_DMA_STATUS_UP_IDLE BIT(8)
#define AR9170_USB_DMA_STATUS_DN_IDLE BIT(16)
#define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110)
#define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114)
#define AR9170_USB_REG_WAKE_UP (AR9170_USB_REG_BASE + 0x120)
#define AR9170_USB_WAKE_UP_WAKE BIT(0)
#define AR9170_USB_REG_CBUS_CTRL (AR9170_USB_REG_BASE + 0x1f0)
#define AR9170_USB_CBUS_CTRL_BUFFER_END (BIT(1))
/* PCI/USB to AHB Bridge */
#define AR9170_PTA_REG_BASE 0x1e2000
#define AR9170_PTA_REG_CMD (AR9170_PTA_REG_BASE + 0x000)
#define AR9170_PTA_REG_PARAM1 (AR9170_PTA_REG_BASE + 0x004)
#define AR9170_PTA_REG_PARAM2 (AR9170_PTA_REG_BASE + 0x008)
#define AR9170_PTA_REG_PARAM3 (AR9170_PTA_REG_BASE + 0x00c)
#define AR9170_PTA_REG_RSP (AR9170_PTA_REG_BASE + 0x010)
#define AR9170_PTA_REG_STATUS1 (AR9170_PTA_REG_BASE + 0x014)
#define AR9170_PTA_REG_STATUS2 (AR9170_PTA_REG_BASE + 0x018)
#define AR9170_PTA_REG_STATUS3 (AR9170_PTA_REG_BASE + 0x01c)
#define AR9170_PTA_REG_AHB_INT_FLAG (AR9170_PTA_REG_BASE + 0x020)
#define AR9170_PTA_REG_AHB_INT_MASK (AR9170_PTA_REG_BASE + 0x024)
#define AR9170_PTA_REG_AHB_INT_ACK (AR9170_PTA_REG_BASE + 0x028)
#define AR9170_PTA_REG_AHB_SCRATCH1 (AR9170_PTA_REG_BASE + 0x030)
#define AR9170_PTA_REG_AHB_SCRATCH2 (AR9170_PTA_REG_BASE + 0x034)
#define AR9170_PTA_REG_AHB_SCRATCH3 (AR9170_PTA_REG_BASE + 0x038)
#define AR9170_PTA_REG_AHB_SCRATCH4 (AR9170_PTA_REG_BASE + 0x03c)
#define AR9170_PTA_REG_SHARE_MEM_CTRL (AR9170_PTA_REG_BASE + 0x124)
/*
* PCI to AHB Bridge
*/
#define AR9170_PTA_REG_INT_FLAG (AR9170_PTA_REG_BASE + 0x100)
#define AR9170_PTA_INT_FLAG_DN 0x01
#define AR9170_PTA_INT_FLAG_UP 0x02
#define AR9170_PTA_INT_FLAG_CMD 0x04
#define AR9170_PTA_REG_INT_MASK (AR9170_PTA_REG_BASE + 0x104)
#define AR9170_PTA_REG_DN_DMA_ADDRL (AR9170_PTA_REG_BASE + 0x108)
#define AR9170_PTA_REG_DN_DMA_ADDRH (AR9170_PTA_REG_BASE + 0x10c)
#define AR9170_PTA_REG_UP_DMA_ADDRL (AR9170_PTA_REG_BASE + 0x110)
#define AR9170_PTA_REG_UP_DMA_ADDRH (AR9170_PTA_REG_BASE + 0x114)
#define AR9170_PTA_REG_DN_PEND_TIME (AR9170_PTA_REG_BASE + 0x118)
#define AR9170_PTA_REG_UP_PEND_TIME (AR9170_PTA_REG_BASE + 0x11c)
#define AR9170_PTA_REG_CONTROL (AR9170_PTA_REG_BASE + 0x120)
#define AR9170_PTA_CTRL_4_BEAT_BURST 0x00
#define AR9170_PTA_CTRL_8_BEAT_BURST 0x01
#define AR9170_PTA_CTRL_16_BEAT_BURST 0x02
#define AR9170_PTA_CTRL_LOOPBACK_MODE 0x10
#define AR9170_PTA_REG_MEM_CTRL (AR9170_PTA_REG_BASE + 0x124)
#define AR9170_PTA_REG_MEM_ADDR (AR9170_PTA_REG_BASE + 0x128)
#define AR9170_PTA_REG_DN_DMA_TRIGGER (AR9170_PTA_REG_BASE + 0x12c)
#define AR9170_PTA_REG_UP_DMA_TRIGGER (AR9170_PTA_REG_BASE + 0x130)
#define AR9170_PTA_REG_DMA_STATUS (AR9170_PTA_REG_BASE + 0x134)
#define AR9170_PTA_REG_DN_CURR_ADDRL (AR9170_PTA_REG_BASE + 0x138)
#define AR9170_PTA_REG_DN_CURR_ADDRH (AR9170_PTA_REG_BASE + 0x13c)
#define AR9170_PTA_REG_UP_CURR_ADDRL (AR9170_PTA_REG_BASE + 0x140)
#define AR9170_PTA_REG_UP_CURR_ADDRH (AR9170_PTA_REG_BASE + 0x144)
#define AR9170_PTA_REG_DMA_MODE_CTRL (AR9170_PTA_REG_BASE + 0x148)
#define AR9170_PTA_DMA_MODE_CTRL_RESET BIT(0)
#define AR9170_PTA_DMA_MODE_CTRL_DISABLE_USB BIT(1)
/* Protocol Controller Module */
#define AR9170_MAC_REG_PC_REG_BASE (AR9170_MAC_REG_BASE + 0xe00)
#define AR9170_NUM_LEDS 2
/* CAM */
#define AR9170_CAM_MAX_USER 64
#define AR9170_CAM_MAX_KEY_LENGTH 16
#define AR9170_SRAM_OFFSET 0x100000
#define AR9170_SRAM_SIZE 0x18000
#define AR9170_PRAM_OFFSET 0x200000
#define AR9170_PRAM_SIZE 0x8000
enum cpu_clock {
AHB_STATIC_40MHZ = 0,
AHB_GMODE_22MHZ = 1,
AHB_AMODE_20MHZ = 1,
AHB_GMODE_44MHZ = 2,
AHB_AMODE_40MHZ = 2,
AHB_GMODE_88MHZ = 3,
AHB_AMODE_80MHZ = 3
};
/* USB endpoints */
enum ar9170_usb_ep {
/*
* Control EP is always EP 0 (USB SPEC)
*
* The weird thing is: the original firmware has a few
* comments that suggest that the actual EP numbers
* are in the 1 to 10 range?!
*/
AR9170_USB_EP_CTRL = 0,
AR9170_USB_EP_TX,
AR9170_USB_EP_RX,
AR9170_USB_EP_IRQ,
AR9170_USB_EP_CMD,
AR9170_USB_NUM_EXTRA_EP = 4,
__AR9170_USB_NUM_EP,
__AR9170_USB_NUM_MAX_EP = 10
};
enum ar9170_usb_fifo {
__AR9170_USB_NUM_MAX_FIFO = 10
};
enum ar9170_tx_queues {
AR9170_TXQ0 = 0,
AR9170_TXQ1,
AR9170_TXQ2,
AR9170_TXQ3,
AR9170_TXQ_SPECIAL,
/* keep last */
__AR9170_NUM_TX_QUEUES = 5
};
#define AR9170_TX_STREAM_TAG 0x697e
#define AR9170_RX_STREAM_TAG 0x4e00
#define AR9170_RX_STREAM_MAX_SIZE 0xffff
struct ar9170_stream {
__le16 length;
__le16 tag;
u8 payload[0];
} __packed __aligned(4);
#define AR9170_STREAM_LEN 4
#define AR9170_MAX_ACKTABLE_ENTRIES 8
#define AR9170_MAX_VIRTUAL_MAC 7
#define AR9170_USB_EP_CTRL_MAX 64
#define AR9170_USB_EP_TX_MAX 512
#define AR9170_USB_EP_RX_MAX 512
#define AR9170_USB_EP_IRQ_MAX 64
#define AR9170_USB_EP_CMD_MAX 64
/* Trigger PRETBTT interrupt 6 Kus earlier */
#define CARL9170_PRETBTT_KUS 6
#define AR5416_MAX_RATE_POWER 63
#define SET_VAL(reg, value, newvalue) \
(value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg))
#define SET_CONSTVAL(reg, newvalue) \
(((newvalue) << reg##_S) & reg)
#define MOD_VAL(reg, value, newvalue) \
(((value) & ~reg) | (((newvalue) << reg##_S) & reg))
#define GET_VAL(reg, value) \
(((value) & reg) >> reg##_S)
#endif /* __CARL9170_SHARED_HW_H */

View File

@@ -0,0 +1,190 @@
/*
* Atheros CARL9170 driver
*
* LED handling
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2009, 2010, Christian Lamparer <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#include "carl9170.h"
#include "cmd.h"
int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state)
{
return carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_DATA, led_state);
}
int carl9170_led_init(struct ar9170 *ar)
{
int err;
/* disable LEDs */
/* GPIO [0/1 mode: output, 2/3: input] */
err = carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3);
if (err)
goto out;
/* GPIO 0/1 value: off */
err = carl9170_led_set_state(ar, 0);
out:
return err;
}
#ifdef CONFIG_CARL9170_LEDS
static void carl9170_led_update(struct work_struct *work)
{
struct ar9170 *ar = container_of(work, struct ar9170, led_work.work);
int i, tmp = 300, blink_delay = 1000;
u32 led_val = 0;
bool rerun = false;
if (!IS_ACCEPTING_CMD(ar))
return;
mutex_lock(&ar->mutex);
for (i = 0; i < AR9170_NUM_LEDS; i++) {
if (ar->leds[i].registered) {
if (ar->leds[i].last_state ||
ar->leds[i].toggled) {
if (ar->leds[i].toggled)
tmp = 70 + 200 / (ar->leds[i].toggled);
if (tmp < blink_delay)
blink_delay = tmp;
led_val |= 1 << i;
ar->leds[i].toggled = 0;
rerun = true;
}
}
}
carl9170_led_set_state(ar, led_val);
mutex_unlock(&ar->mutex);
if (!rerun)
return;
ieee80211_queue_delayed_work(ar->hw,
&ar->led_work,
msecs_to_jiffies(blink_delay));
}
static void carl9170_led_set_brightness(struct led_classdev *led,
enum led_brightness brightness)
{
struct carl9170_led *arl = container_of(led, struct carl9170_led, l);
struct ar9170 *ar = arl->ar;
if (!arl->registered)
return;
if (arl->last_state != !!brightness) {
arl->toggled++;
arl->last_state = !!brightness;
}
if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ / 10);
}
static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name,
char *trigger)
{
int err;
snprintf(ar->leds[i].name, sizeof(ar->leds[i].name),
"carl9170-%s::%s", wiphy_name(ar->hw->wiphy), name);
ar->leds[i].ar = ar;
ar->leds[i].l.name = ar->leds[i].name;
ar->leds[i].l.brightness_set = carl9170_led_set_brightness;
ar->leds[i].l.brightness = 0;
ar->leds[i].l.default_trigger = trigger;
err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
&ar->leds[i].l);
if (err) {
wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n",
ar->leds[i].name, err);
} else {
ar->leds[i].registered = true;
}
return err;
}
void carl9170_led_unregister(struct ar9170 *ar)
{
int i;
for (i = 0; i < AR9170_NUM_LEDS; i++)
if (ar->leds[i].registered) {
led_classdev_unregister(&ar->leds[i].l);
ar->leds[i].registered = false;
ar->leds[i].toggled = 0;
}
cancel_delayed_work_sync(&ar->led_work);
}
int carl9170_led_register(struct ar9170 *ar)
{
int err;
INIT_DELAYED_WORK(&ar->led_work, carl9170_led_update);
err = carl9170_led_register_led(ar, 0, "tx",
ieee80211_get_tx_led_name(ar->hw));
if (err)
goto fail;
if (ar->features & CARL9170_ONE_LED)
return 0;
err = carl9170_led_register_led(ar, 1, "assoc",
ieee80211_get_assoc_led_name(ar->hw));
if (err)
goto fail;
return 0;
fail:
carl9170_led_unregister(ar);
return err;
}
#endif /* CONFIG_CARL9170_LEDS */

View File

@@ -0,0 +1,538 @@
/*
* Atheros CARL9170 driver
*
* MAC programming
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#include <asm/unaligned.h>
#include "carl9170.h"
#include "cmd.h"
int carl9170_set_dyn_sifs_ack(struct ar9170 *ar)
{
u32 val;
if (conf_is_ht40(&ar->hw->conf))
val = 0x010a;
else {
if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
val = 0x105;
else
val = 0x104;
}
return carl9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val);
}
int carl9170_set_rts_cts_rate(struct ar9170 *ar)
{
u32 rts_rate, cts_rate;
if (conf_is_ht(&ar->hw->conf)) {
/* 12 mbit OFDM */
rts_rate = 0x1da;
cts_rate = 0x10a;
} else {
if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
/* 11 mbit CCK */
rts_rate = 033;
cts_rate = 003;
} else {
/* 6 mbit OFDM */
rts_rate = 0x1bb;
cts_rate = 0x10b;
}
}
return carl9170_write_reg(ar, AR9170_MAC_REG_RTS_CTS_RATE,
rts_rate | (cts_rate) << 16);
}
int carl9170_set_slot_time(struct ar9170 *ar)
{
struct ieee80211_vif *vif;
u32 slottime = 20;
rcu_read_lock();
vif = carl9170_get_main_vif(ar);
if (!vif) {
rcu_read_unlock();
return 0;
}
if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) ||
vif->bss_conf.use_short_slot)
slottime = 9;
rcu_read_unlock();
return carl9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME,
slottime << 10);
}
int carl9170_set_mac_rates(struct ar9170 *ar)
{
struct ieee80211_vif *vif;
u32 basic, mandatory;
rcu_read_lock();
vif = carl9170_get_main_vif(ar);
if (!vif) {
rcu_read_unlock();
return 0;
}
basic = (vif->bss_conf.basic_rates & 0xf);
basic |= (vif->bss_conf.basic_rates & 0xff0) << 4;
rcu_read_unlock();
if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */
else
mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */
carl9170_regwrite_begin(ar);
carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, basic);
carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, mandatory);
carl9170_regwrite_finish();
return carl9170_regwrite_result();
}
int carl9170_set_qos(struct ar9170 *ar)
{
carl9170_regwrite_begin(ar);
carl9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min |
(ar->edcf[0].cw_max << 16));
carl9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min |
(ar->edcf[1].cw_max << 16));
carl9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min |
(ar->edcf[2].cw_max << 16));
carl9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min |
(ar->edcf[3].cw_max << 16));
carl9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min |
(ar->edcf[4].cw_max << 16));
carl9170_regwrite(AR9170_MAC_REG_AC2_AC1_AC0_AIFS,
((ar->edcf[0].aifs * 9 + 10)) |
((ar->edcf[1].aifs * 9 + 10) << 12) |
((ar->edcf[2].aifs * 9 + 10) << 24));
carl9170_regwrite(AR9170_MAC_REG_AC4_AC3_AC2_AIFS,
((ar->edcf[2].aifs * 9 + 10) >> 8) |
((ar->edcf[3].aifs * 9 + 10) << 4) |
((ar->edcf[4].aifs * 9 + 10) << 16));
carl9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP,
ar->edcf[0].txop | ar->edcf[1].txop << 16);
carl9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP,
ar->edcf[2].txop | ar->edcf[3].txop << 16 |
ar->edcf[4].txop << 24);
carl9170_regwrite_finish();
return carl9170_regwrite_result();
}
int carl9170_init_mac(struct ar9170 *ar)
{
carl9170_regwrite_begin(ar);
/* switch MAC to OTUS interface */
carl9170_regwrite(0x1c3600, 0x3);
carl9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40);
carl9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0x0);
carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
AR9170_MAC_FTF_MONITOR);
/* enable MMIC */
carl9170_regwrite(AR9170_MAC_REG_SNIFFER,
AR9170_MAC_SNIFFER_DEFAULTS);
carl9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80);
carl9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70);
carl9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000);
carl9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10);
/* CF-END & CF-ACK rate => 24M OFDM */
carl9170_regwrite(AR9170_MAC_REG_TID_CFACK_CFEND_RATE, 0x59900000);
/* NAV protects ACK only (in TXOP) */
carl9170_regwrite(AR9170_MAC_REG_TXOP_DURATION, 0x201);
/* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */
/* OTUS set AM to 0x1 */
carl9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170);
carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
/* Aggregation MAX number and timeout */
carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0x8000a);
carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a07);
carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
AR9170_MAC_FTF_DEFAULTS);
carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL,
AR9170_MAC_RX_CTRL_DEAGG |
AR9170_MAC_RX_CTRL_SHORT_FILTER);
/* rate sets */
carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f);
carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f);
carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x0030033);
/* MIMO response control */
carl9170_regwrite(AR9170_MAC_REG_ACK_TPC, 0x4003c1e);
carl9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff);
/* set PHY register read timeout (??) */
carl9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008);
/* Disable Rx TimeOut, workaround for BB. */
carl9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0);
/* Set WLAN DMA interrupt mode: generate int per packet */
carl9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011);
carl9170_regwrite(AR9170_MAC_REG_FCS_SELECT,
AR9170_MAC_FCS_FIFO_PROT);
/* Disables the CF_END frame, undocumented register */
carl9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND,
0x141e0f48);
/* reset group hash table */
carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, 0xffffffff);
carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, 0xffffffff);
/* disable PRETBTT interrupt */
carl9170_regwrite(AR9170_MAC_REG_PRETBTT, 0x0);
carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, 0x0);
carl9170_regwrite_finish();
return carl9170_regwrite_result();
}
static int carl9170_set_mac_reg(struct ar9170 *ar,
const u32 reg, const u8 *mac)
{
static const u8 zero[ETH_ALEN] = { 0 };
if (!mac)
mac = zero;
carl9170_regwrite_begin(ar);
carl9170_regwrite(reg, get_unaligned_le32(mac));
carl9170_regwrite(reg + 4, get_unaligned_le16(mac + 4));
carl9170_regwrite_finish();
return carl9170_regwrite_result();
}
int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id,
const u8 *mac)
{
if (WARN_ON(id >= ar->fw.vif_num))
return -EINVAL;
return carl9170_set_mac_reg(ar,
AR9170_MAC_REG_ACK_TABLE + (id - 1) * 8, mac);
}
int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hash)
{
int err;
carl9170_regwrite_begin(ar);
carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32);
carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash);
carl9170_regwrite_finish();
err = carl9170_regwrite_result();
if (err)
return err;
ar->cur_mc_hash = mc_hash;
return 0;
}
int carl9170_set_operating_mode(struct ar9170 *ar)
{
struct ieee80211_vif *vif;
struct ath_common *common = &ar->common;
u8 *mac_addr, *bssid;
u32 cam_mode = AR9170_MAC_CAM_DEFAULTS;
u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS |
AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE;
u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG |
AR9170_MAC_RX_CTRL_SHORT_FILTER;
u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS;
int err = 0;
rcu_read_lock();
vif = carl9170_get_main_vif(ar);
if (vif) {
mac_addr = common->macaddr;
bssid = common->curbssid;
switch (vif->type) {
case NL80211_IFTYPE_ADHOC:
cam_mode |= AR9170_MAC_CAM_IBSS;
break;
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
cam_mode |= AR9170_MAC_CAM_AP;
/* iwlagn 802.11n STA Workaround */
rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
break;
case NL80211_IFTYPE_WDS:
cam_mode |= AR9170_MAC_CAM_AP_WDS;
rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
break;
case NL80211_IFTYPE_STATION:
cam_mode |= AR9170_MAC_CAM_STA;
rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
break;
default:
WARN(1, "Unsupported operation mode %x\n", vif->type);
err = -EOPNOTSUPP;
break;
}
} else {
/*
* Enable monitor mode
*
* rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
* sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
*
* When the hardware is in SNIFFER_PROMISC mode,
* it generates spurious ACKs for every incoming
* frame. This confuses every peer in the
* vicinity and the network throughput will suffer
* badly.
*
* Hence, the hardware will be put into station
* mode and just the rx filters are disabled.
*/
cam_mode |= AR9170_MAC_CAM_STA;
rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
mac_addr = common->macaddr;
bssid = NULL;
}
rcu_read_unlock();
if (err)
return err;
if (ar->rx_software_decryption)
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
if (ar->sniffer_enabled) {
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
}
err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr);
if (err)
return err;
err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid);
if (err)
return err;
carl9170_regwrite_begin(ar);
carl9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer);
carl9170_regwrite(AR9170_MAC_REG_CAM_MODE, cam_mode);
carl9170_regwrite(AR9170_MAC_REG_ENCRYPTION, enc_mode);
carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL, rx_ctrl);
carl9170_regwrite_finish();
return carl9170_regwrite_result();
}
int carl9170_set_hwretry_limit(struct ar9170 *ar, const unsigned int max_retry)
{
u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111);
return carl9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp);
}
int carl9170_set_beacon_timers(struct ar9170 *ar)
{
struct ieee80211_vif *vif;
u32 v = 0;
u32 pretbtt = 0;
rcu_read_lock();
vif = carl9170_get_main_vif(ar);
if (vif) {
struct carl9170_vif_info *mvif;
mvif = (void *) vif->drv_priv;
if (mvif->enable_beacon && !WARN_ON(!ar->beacon_enabled)) {
ar->global_beacon_int = vif->bss_conf.beacon_int /
ar->beacon_enabled;
SET_VAL(AR9170_MAC_BCN_DTIM, v,
vif->bss_conf.dtim_period);
switch (vif->type) {
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_ADHOC:
v |= AR9170_MAC_BCN_IBSS_MODE;
break;
case NL80211_IFTYPE_AP:
v |= AR9170_MAC_BCN_AP_MODE;
break;
default:
WARN_ON_ONCE(1);
break;
}
} else if (vif->type == NL80211_IFTYPE_STATION) {
ar->global_beacon_int = vif->bss_conf.beacon_int;
SET_VAL(AR9170_MAC_BCN_DTIM, v,
ar->hw->conf.ps_dtim_period);
v |= AR9170_MAC_BCN_STA_PS |
AR9170_MAC_BCN_PWR_MGT;
}
if (ar->global_beacon_int) {
if (ar->global_beacon_int < 15) {
rcu_read_unlock();
return -ERANGE;
}
ar->global_pretbtt = ar->global_beacon_int -
CARL9170_PRETBTT_KUS;
} else {
ar->global_pretbtt = 0;
}
} else {
ar->global_beacon_int = 0;
ar->global_pretbtt = 0;
}
rcu_read_unlock();
SET_VAL(AR9170_MAC_BCN_PERIOD, v, ar->global_beacon_int);
SET_VAL(AR9170_MAC_PRETBTT, pretbtt, ar->global_pretbtt);
SET_VAL(AR9170_MAC_PRETBTT2, pretbtt, ar->global_pretbtt);
carl9170_regwrite_begin(ar);
carl9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt);
carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v);
carl9170_regwrite_finish();
return carl9170_regwrite_result();
}
int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
const u8 ktype, const u8 keyidx, const u8 *keydata,
const int keylen)
{
struct carl9170_set_key_cmd key = { };
static const u8 bcast[ETH_ALEN] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
mac = mac ? : bcast;
key.user = cpu_to_le16(id);
key.keyId = cpu_to_le16(keyidx);
key.type = cpu_to_le16(ktype);
memcpy(&key.macAddr, mac, ETH_ALEN);
if (keydata)
memcpy(&key.key, keydata, keylen);
return carl9170_exec_cmd(ar, CARL9170_CMD_EKEY,
sizeof(key), (u8 *)&key, 0, NULL);
}
int carl9170_disable_key(struct ar9170 *ar, const u8 id)
{
struct carl9170_disable_key_cmd key = { };
key.user = cpu_to_le16(id);
return carl9170_exec_cmd(ar, CARL9170_CMD_DKEY,
sizeof(key), (u8 *)&key, 0, NULL);
}
int carl9170_set_mac_tpc(struct ar9170 *ar, struct ieee80211_channel *channel)
{
unsigned int power, chains;
if (ar->eeprom.tx_mask != 1)
chains = AR9170_TX_PHY_TXCHAIN_2;
else
chains = AR9170_TX_PHY_TXCHAIN_1;
switch (channel->band) {
case IEEE80211_BAND_2GHZ:
power = ar->power_2G_ofdm[0] & 0x3f;
break;
case IEEE80211_BAND_5GHZ:
power = ar->power_5G_leg[0] & 0x3f;
break;
default:
BUG_ON(1);
}
power = min_t(unsigned int, power, ar->hw->conf.power_level * 2);
carl9170_regwrite_begin(ar);
carl9170_regwrite(AR9170_MAC_REG_ACK_TPC,
0x3c1e | power << 20 | chains << 26);
carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_TPC,
power << 5 | chains << 11 |
power << 21 | chains << 27);
carl9170_regwrite(AR9170_MAC_REG_CFEND_QOSNULL_TPC,
power << 5 | chains << 11 |
power << 21 | chains << 27);
carl9170_regwrite_finish();
return carl9170_regwrite_result();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,564 @@
/*
* Shared Atheros AR9170 Header
*
* PHY register map
*
* Copyright (c) 2008-2009 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#ifndef __CARL9170_SHARED_PHY_H
#define __CARL9170_SHARED_PHY_H
#define AR9170_PHY_REG_BASE (0x1bc000 + 0x9800)
#define AR9170_PHY_REG(_n) (AR9170_PHY_REG_BASE + \
((_n) << 2))
#define AR9170_PHY_REG_TEST (AR9170_PHY_REG_BASE + 0x0000)
#define AR9170_PHY_TEST_AGC_CLR 0x10000000
#define AR9170_PHY_TEST_RFSILENT_BB 0x00002000
#define AR9170_PHY_REG_TURBO (AR9170_PHY_REG_BASE + 0x0004)
#define AR9170_PHY_TURBO_FC_TURBO_MODE 0x00000001
#define AR9170_PHY_TURBO_FC_TURBO_SHORT 0x00000002
#define AR9170_PHY_TURBO_FC_DYN2040_EN 0x00000004
#define AR9170_PHY_TURBO_FC_DYN2040_PRI_ONLY 0x00000008
#define AR9170_PHY_TURBO_FC_DYN2040_PRI_CH 0x00000010
/* For 25 MHz channel spacing -- not used but supported by hw */
#define AR9170_PHY_TURBO_FC_DYN2040_EXT_CH 0x00000020
#define AR9170_PHY_TURBO_FC_HT_EN 0x00000040
#define AR9170_PHY_TURBO_FC_SHORT_GI_40 0x00000080
#define AR9170_PHY_TURBO_FC_WALSH 0x00000100
#define AR9170_PHY_TURBO_FC_SINGLE_HT_LTF1 0x00000200
#define AR9170_PHY_TURBO_FC_ENABLE_DAC_FIFO 0x00000800
#define AR9170_PHY_REG_TEST2 (AR9170_PHY_REG_BASE + 0x0008)
#define AR9170_PHY_REG_TIMING2 (AR9170_PHY_REG_BASE + 0x0010)
#define AR9170_PHY_TIMING2_USE_FORCE 0x00001000
#define AR9170_PHY_TIMING2_FORCE 0x00000fff
#define AR9170_PHY_TIMING2_FORCE_S 0
#define AR9170_PHY_REG_TIMING3 (AR9170_PHY_REG_BASE + 0x0014)
#define AR9170_PHY_TIMING3_DSC_EXP 0x0001e000
#define AR9170_PHY_TIMING3_DSC_EXP_S 13
#define AR9170_PHY_TIMING3_DSC_MAN 0xfffe0000
#define AR9170_PHY_TIMING3_DSC_MAN_S 17
#define AR9170_PHY_REG_CHIP_ID (AR9170_PHY_REG_BASE + 0x0018)
#define AR9170_PHY_CHIP_ID_REV_0 0x80
#define AR9170_PHY_CHIP_ID_REV_1 0x81
#define AR9170_PHY_CHIP_ID_9160_REV_0 0xb0
#define AR9170_PHY_REG_ACTIVE (AR9170_PHY_REG_BASE + 0x001c)
#define AR9170_PHY_ACTIVE_EN 0x00000001
#define AR9170_PHY_ACTIVE_DIS 0x00000000
#define AR9170_PHY_REG_RF_CTL2 (AR9170_PHY_REG_BASE + 0x0024)
#define AR9170_PHY_RF_CTL2_TX_END_DATA_START 0x000000ff
#define AR9170_PHY_RF_CTL2_TX_END_DATA_START_S 0
#define AR9170_PHY_RF_CTL2_TX_END_PA_ON 0x0000ff00
#define AR9170_PHY_RF_CTL2_TX_END_PA_ON_S 8
#define AR9170_PHY_REG_RF_CTL3 (AR9170_PHY_REG_BASE + 0x0028)
#define AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON 0x00ff0000
#define AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON_S 16
#define AR9170_PHY_REG_ADC_CTL (AR9170_PHY_REG_BASE + 0x002c)
#define AR9170_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
#define AR9170_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
#define AR9170_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
#define AR9170_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000
#define AR9170_PHY_ADC_CTL_OFF_PWDADC 0x00008000
#define AR9170_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000
#define AR9170_PHY_ADC_CTL_ON_INBUFGAIN_S 16
#define AR9170_PHY_REG_ADC_SERIAL_CTL (AR9170_PHY_REG_BASE + 0x0030)
#define AR9170_PHY_ADC_SCTL_SEL_INTERNAL_ADDAC 0x00000000
#define AR9170_PHY_ADC_SCTL_SEL_EXTERNAL_RADIO 0x00000001
#define AR9170_PHY_REG_RF_CTL4 (AR9170_PHY_REG_BASE + 0x0034)
#define AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF 0xff000000
#define AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
#define AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00ff0000
#define AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
#define AR9170_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000ff00
#define AR9170_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
#define AR9170_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000ff
#define AR9170_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
#define AR9170_PHY_REG_TSTDAC_CONST (AR9170_PHY_REG_BASE + 0x003c)
#define AR9170_PHY_REG_SETTLING (AR9170_PHY_REG_BASE + 0x0044)
#define AR9170_PHY_SETTLING_SWITCH 0x00003f80
#define AR9170_PHY_SETTLING_SWITCH_S 7
#define AR9170_PHY_REG_RXGAIN (AR9170_PHY_REG_BASE + 0x0048)
#define AR9170_PHY_REG_RXGAIN_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2048)
#define AR9170_PHY_RXGAIN_TXRX_ATTEN 0x0003f000
#define AR9170_PHY_RXGAIN_TXRX_ATTEN_S 12
#define AR9170_PHY_RXGAIN_TXRX_RF_MAX 0x007c0000
#define AR9170_PHY_RXGAIN_TXRX_RF_MAX_S 18
#define AR9170_PHY_REG_DESIRED_SZ (AR9170_PHY_REG_BASE + 0x0050)
#define AR9170_PHY_DESIRED_SZ_ADC 0x000000ff
#define AR9170_PHY_DESIRED_SZ_ADC_S 0
#define AR9170_PHY_DESIRED_SZ_PGA 0x0000ff00
#define AR9170_PHY_DESIRED_SZ_PGA_S 8
#define AR9170_PHY_DESIRED_SZ_TOT_DES 0x0ff00000
#define AR9170_PHY_DESIRED_SZ_TOT_DES_S 20
#define AR9170_PHY_REG_FIND_SIG (AR9170_PHY_REG_BASE + 0x0058)
#define AR9170_PHY_FIND_SIG_FIRSTEP 0x0003f000
#define AR9170_PHY_FIND_SIG_FIRSTEP_S 12
#define AR9170_PHY_FIND_SIG_FIRPWR 0x03fc0000
#define AR9170_PHY_FIND_SIG_FIRPWR_S 18
#define AR9170_PHY_REG_AGC_CTL1 (AR9170_PHY_REG_BASE + 0x005c)
#define AR9170_PHY_AGC_CTL1_COARSE_LOW 0x00007f80
#define AR9170_PHY_AGC_CTL1_COARSE_LOW_S 7
#define AR9170_PHY_AGC_CTL1_COARSE_HIGH 0x003f8000
#define AR9170_PHY_AGC_CTL1_COARSE_HIGH_S 15
#define AR9170_PHY_REG_AGC_CONTROL (AR9170_PHY_REG_BASE + 0x0060)
#define AR9170_PHY_AGC_CONTROL_CAL 0x00000001
#define AR9170_PHY_AGC_CONTROL_NF 0x00000002
#define AR9170_PHY_AGC_CONTROL_ENABLE_NF 0x00008000
#define AR9170_PHY_AGC_CONTROL_FLTR_CAL 0x00010000
#define AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000
#define AR9170_PHY_REG_CCA (AR9170_PHY_REG_BASE + 0x0064)
#define AR9170_PHY_CCA_MIN_PWR 0x0ff80000
#define AR9170_PHY_CCA_MIN_PWR_S 19
#define AR9170_PHY_CCA_THRESH62 0x0007f000
#define AR9170_PHY_CCA_THRESH62_S 12
#define AR9170_PHY_REG_SFCORR (AR9170_PHY_REG_BASE + 0x0068)
#define AR9170_PHY_SFCORR_M2COUNT_THR 0x0000001f
#define AR9170_PHY_SFCORR_M2COUNT_THR_S 0
#define AR9170_PHY_SFCORR_M1_THRESH 0x00fe0000
#define AR9170_PHY_SFCORR_M1_THRESH_S 17
#define AR9170_PHY_SFCORR_M2_THRESH 0x7f000000
#define AR9170_PHY_SFCORR_M2_THRESH_S 24
#define AR9170_PHY_REG_SFCORR_LOW (AR9170_PHY_REG_BASE + 0x006c)
#define AR9170_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
#define AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003f00
#define AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
#define AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001fc000
#define AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
#define AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0fe00000
#define AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
#define AR9170_PHY_REG_SLEEP_CTR_CONTROL (AR9170_PHY_REG_BASE + 0x0070)
#define AR9170_PHY_REG_SLEEP_CTR_LIMIT (AR9170_PHY_REG_BASE + 0x0074)
#define AR9170_PHY_REG_SLEEP_SCAL (AR9170_PHY_REG_BASE + 0x0078)
#define AR9170_PHY_REG_PLL_CTL (AR9170_PHY_REG_BASE + 0x007c)
#define AR9170_PHY_PLL_CTL_40 0xaa
#define AR9170_PHY_PLL_CTL_40_5413 0x04
#define AR9170_PHY_PLL_CTL_44 0xab
#define AR9170_PHY_PLL_CTL_44_2133 0xeb
#define AR9170_PHY_PLL_CTL_40_2133 0xea
#define AR9170_PHY_REG_BIN_MASK_1 (AR9170_PHY_REG_BASE + 0x0100)
#define AR9170_PHY_REG_BIN_MASK_2 (AR9170_PHY_REG_BASE + 0x0104)
#define AR9170_PHY_REG_BIN_MASK_3 (AR9170_PHY_REG_BASE + 0x0108)
#define AR9170_PHY_REG_MASK_CTL (AR9170_PHY_REG_BASE + 0x010c)
/* analogue power on time (100ns) */
#define AR9170_PHY_REG_RX_DELAY (AR9170_PHY_REG_BASE + 0x0114)
#define AR9170_PHY_REG_SEARCH_START_DELAY (AR9170_PHY_REG_BASE + 0x0118)
#define AR9170_PHY_RX_DELAY_DELAY 0x00003fff
#define AR9170_PHY_REG_TIMING_CTRL4(_i) (AR9170_PHY_REG_BASE + \
(0x0120 + ((_i) << 12)))
#define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01f
#define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0
#define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7e0
#define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5
#define AR9170_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800
#define AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xf000
#define AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12
#define AR9170_PHY_TIMING_CTRL4_DO_IQCAL 0x10000
#define AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000
#define AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000
#define AR9170_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000
#define AR9170_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000
#define AR9170_PHY_REG_TIMING5 (AR9170_PHY_REG_BASE + 0x0124)
#define AR9170_PHY_TIMING5_CYCPWR_THR1 0x000000fe
#define AR9170_PHY_TIMING5_CYCPWR_THR1_S 1
#define AR9170_PHY_REG_POWER_TX_RATE1 (AR9170_PHY_REG_BASE + 0x0134)
#define AR9170_PHY_REG_POWER_TX_RATE2 (AR9170_PHY_REG_BASE + 0x0138)
#define AR9170_PHY_REG_POWER_TX_RATE_MAX (AR9170_PHY_REG_BASE + 0x013c)
#define AR9170_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
#define AR9170_PHY_REG_FRAME_CTL (AR9170_PHY_REG_BASE + 0x0144)
#define AR9170_PHY_FRAME_CTL_TX_CLIP 0x00000038
#define AR9170_PHY_FRAME_CTL_TX_CLIP_S 3
#define AR9170_PHY_REG_SPUR_REG (AR9170_PHY_REG_BASE + 0x014c)
#define AR9170_PHY_SPUR_REG_MASK_RATE_CNTL (0xff << 18)
#define AR9170_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
#define AR9170_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000
#define AR9170_PHY_SPUR_REG_MASK_RATE_SELECT (0xff << 9)
#define AR9170_PHY_SPUR_REG_MASK_RATE_SELECT_S 9
#define AR9170_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
#define AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7f
#define AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
#define AR9170_PHY_REG_RADAR_EXT (AR9170_PHY_REG_BASE + 0x0140)
#define AR9170_PHY_RADAR_EXT_ENA 0x00004000
#define AR9170_PHY_REG_RADAR_0 (AR9170_PHY_REG_BASE + 0x0154)
#define AR9170_PHY_RADAR_0_ENA 0x00000001
#define AR9170_PHY_RADAR_0_FFT_ENA 0x80000000
/* inband pulse threshold */
#define AR9170_PHY_RADAR_0_INBAND 0x0000003e
#define AR9170_PHY_RADAR_0_INBAND_S 1
/* pulse RSSI threshold */
#define AR9170_PHY_RADAR_0_PRSSI 0x00000fc0
#define AR9170_PHY_RADAR_0_PRSSI_S 6
/* pulse height threshold */
#define AR9170_PHY_RADAR_0_HEIGHT 0x0003f000
#define AR9170_PHY_RADAR_0_HEIGHT_S 12
/* radar RSSI threshold */
#define AR9170_PHY_RADAR_0_RRSSI 0x00fc0000
#define AR9170_PHY_RADAR_0_RRSSI_S 18
/* radar firepower threshold */
#define AR9170_PHY_RADAR_0_FIRPWR 0x7f000000
#define AR9170_PHY_RADAR_0_FIRPWR_S 24
#define AR9170_PHY_REG_RADAR_1 (AR9170_PHY_REG_BASE + 0x0158)
#define AR9170_PHY_RADAR_1_RELPWR_ENA 0x00800000
#define AR9170_PHY_RADAR_1_USE_FIR128 0x00400000
#define AR9170_PHY_RADAR_1_RELPWR_THRESH 0x003f0000
#define AR9170_PHY_RADAR_1_RELPWR_THRESH_S 16
#define AR9170_PHY_RADAR_1_BLOCK_CHECK 0x00008000
#define AR9170_PHY_RADAR_1_MAX_RRSSI 0x00004000
#define AR9170_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
#define AR9170_PHY_RADAR_1_RELSTEP_THRESH 0x00001f00
#define AR9170_PHY_RADAR_1_RELSTEP_THRESH_S 8
#define AR9170_PHY_RADAR_1_MAXLEN 0x000000ff
#define AR9170_PHY_RADAR_1_MAXLEN_S 0
#define AR9170_PHY_REG_SWITCH_CHAIN_0 (AR9170_PHY_REG_BASE + 0x0160)
#define AR9170_PHY_REG_SWITCH_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2160)
#define AR9170_PHY_REG_SWITCH_COM (AR9170_PHY_REG_BASE + 0x0164)
#define AR9170_PHY_REG_CCA_THRESHOLD (AR9170_PHY_REG_BASE + 0x0168)
#define AR9170_PHY_REG_SIGMA_DELTA (AR9170_PHY_REG_BASE + 0x016c)
#define AR9170_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
#define AR9170_PHY_SIGMA_DELTA_ADC_SEL_S 0
#define AR9170_PHY_SIGMA_DELTA_FILT2 0x000000f8
#define AR9170_PHY_SIGMA_DELTA_FILT2_S 3
#define AR9170_PHY_SIGMA_DELTA_FILT1 0x00001f00
#define AR9170_PHY_SIGMA_DELTA_FILT1_S 8
#define AR9170_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000
#define AR9170_PHY_SIGMA_DELTA_ADC_CLIP_S 13
#define AR9170_PHY_REG_RESTART (AR9170_PHY_REG_BASE + 0x0170)
#define AR9170_PHY_RESTART_DIV_GC 0x001c0000
#define AR9170_PHY_RESTART_DIV_GC_S 18
#define AR9170_PHY_REG_RFBUS_REQ (AR9170_PHY_REG_BASE + 0x017c)
#define AR9170_PHY_RFBUS_REQ_EN 0x00000001
#define AR9170_PHY_REG_TIMING7 (AR9170_PHY_REG_BASE + 0x0180)
#define AR9170_PHY_REG_TIMING8 (AR9170_PHY_REG_BASE + 0x0184)
#define AR9170_PHY_TIMING8_PILOT_MASK_2 0x000fffff
#define AR9170_PHY_TIMING8_PILOT_MASK_2_S 0
#define AR9170_PHY_REG_BIN_MASK2_1 (AR9170_PHY_REG_BASE + 0x0188)
#define AR9170_PHY_REG_BIN_MASK2_2 (AR9170_PHY_REG_BASE + 0x018c)
#define AR9170_PHY_REG_BIN_MASK2_3 (AR9170_PHY_REG_BASE + 0x0190)
#define AR9170_PHY_REG_BIN_MASK2_4 (AR9170_PHY_REG_BASE + 0x0194)
#define AR9170_PHY_BIN_MASK2_4_MASK_4 0x00003fff
#define AR9170_PHY_BIN_MASK2_4_MASK_4_S 0
#define AR9170_PHY_REG_TIMING9 (AR9170_PHY_REG_BASE + 0x0198)
#define AR9170_PHY_REG_TIMING10 (AR9170_PHY_REG_BASE + 0x019c)
#define AR9170_PHY_TIMING10_PILOT_MASK_2 0x000fffff
#define AR9170_PHY_TIMING10_PILOT_MASK_2_S 0
#define AR9170_PHY_REG_TIMING11 (AR9170_PHY_REG_BASE + 0x01a0)
#define AR9170_PHY_TIMING11_SPUR_DELTA_PHASE 0x000fffff
#define AR9170_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
#define AR9170_PHY_TIMING11_SPUR_FREQ_SD 0x3ff00000
#define AR9170_PHY_TIMING11_SPUR_FREQ_SD_S 20
#define AR9170_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000
#define AR9170_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000
#define AR9170_PHY_REG_RX_CHAINMASK (AR9170_PHY_REG_BASE + 0x01a4)
#define AR9170_PHY_REG_NEW_ADC_DC_GAIN_CORR(_i) (AR9170_PHY_REG_BASE + \
0x01b4 + ((_i) << 12))
#define AR9170_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
#define AR9170_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
#define AR9170_PHY_REG_MULTICHAIN_GAIN_CTL (AR9170_PHY_REG_BASE + 0x01ac)
#define AR9170_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000
#define AR9170_PHY_9285_ANT_DIV_CTL 0x01000000
#define AR9170_PHY_9285_ANT_DIV_CTL_S 24
#define AR9170_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000
#define AR9170_PHY_9285_ANT_DIV_ALT_LNACONF_S 25
#define AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000
#define AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27
#define AR9170_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000
#define AR9170_PHY_9285_ANT_DIV_ALT_GAINTB_S 29
#define AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000
#define AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30
#define AR9170_PHY_9285_ANT_DIV_LNA1 2
#define AR9170_PHY_9285_ANT_DIV_LNA2 1
#define AR9170_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3
#define AR9170_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
#define AR9170_PHY_9285_ANT_DIV_GAINTB_0 0
#define AR9170_PHY_9285_ANT_DIV_GAINTB_1 1
#define AR9170_PHY_REG_EXT_CCA0 (AR9170_PHY_REG_BASE + 0x01b8)
#define AR9170_PHY_REG_EXT_CCA0_THRESH62 0x000000ff
#define AR9170_PHY_REG_EXT_CCA0_THRESH62_S 0
#define AR9170_PHY_REG_EXT_CCA (AR9170_PHY_REG_BASE + 0x01bc)
#define AR9170_PHY_EXT_CCA_CYCPWR_THR1 0x0000fe00
#define AR9170_PHY_EXT_CCA_CYCPWR_THR1_S 9
#define AR9170_PHY_EXT_CCA_THRESH62 0x007f0000
#define AR9170_PHY_EXT_CCA_THRESH62_S 16
#define AR9170_PHY_EXT_CCA_MIN_PWR 0xff800000
#define AR9170_PHY_EXT_CCA_MIN_PWR_S 23
#define AR9170_PHY_REG_SFCORR_EXT (AR9170_PHY_REG_BASE + 0x01c0)
#define AR9170_PHY_SFCORR_EXT_M1_THRESH 0x0000007f
#define AR9170_PHY_SFCORR_EXT_M1_THRESH_S 0
#define AR9170_PHY_SFCORR_EXT_M2_THRESH 0x00003f80
#define AR9170_PHY_SFCORR_EXT_M2_THRESH_S 7
#define AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001fc000
#define AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
#define AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0fe00000
#define AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
#define AR9170_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
#define AR9170_PHY_REG_HALFGI (AR9170_PHY_REG_BASE + 0x01d0)
#define AR9170_PHY_HALFGI_DSC_MAN 0x0007fff0
#define AR9170_PHY_HALFGI_DSC_MAN_S 4
#define AR9170_PHY_HALFGI_DSC_EXP 0x0000000f
#define AR9170_PHY_HALFGI_DSC_EXP_S 0
#define AR9170_PHY_REG_CHANNEL_MASK_01_30 (AR9170_PHY_REG_BASE + 0x01d4)
#define AR9170_PHY_REG_CHANNEL_MASK_31_60 (AR9170_PHY_REG_BASE + 0x01d8)
#define AR9170_PHY_REG_CHAN_INFO_MEMORY (AR9170_PHY_REG_BASE + 0x01dc)
#define AR9170_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
#define AR9170_PHY_REG_HEAVY_CLIP_ENABLE (AR9170_PHY_REG_BASE + 0x01e0)
#define AR9170_PHY_REG_HEAVY_CLIP_FACTOR_RIFS (AR9170_PHY_REG_BASE + 0x01ec)
#define AR9170_PHY_RIFS_INIT_DELAY 0x03ff0000
#define AR9170_PHY_REG_CALMODE (AR9170_PHY_REG_BASE + 0x01f0)
#define AR9170_PHY_CALMODE_IQ 0x00000000
#define AR9170_PHY_CALMODE_ADC_GAIN 0x00000001
#define AR9170_PHY_CALMODE_ADC_DC_PER 0x00000002
#define AR9170_PHY_CALMODE_ADC_DC_INIT 0x00000003
#define AR9170_PHY_REG_REFCLKDLY (AR9170_PHY_REG_BASE + 0x01f4)
#define AR9170_PHY_REG_REFCLKPD (AR9170_PHY_REG_BASE + 0x01f8)
#define AR9170_PHY_REG_CAL_MEAS_0(_i) (AR9170_PHY_REG_BASE + \
0x0410 + ((_i) << 12))
#define AR9170_PHY_REG_CAL_MEAS_1(_i) (AR9170_PHY_REG_BASE + \
0x0414 \ + ((_i) << 12))
#define AR9170_PHY_REG_CAL_MEAS_2(_i) (AR9170_PHY_REG_BASE + \
0x0418 + ((_i) << 12))
#define AR9170_PHY_REG_CAL_MEAS_3(_i) (AR9170_PHY_REG_BASE + \
0x041c + ((_i) << 12))
#define AR9170_PHY_REG_CURRENT_RSSI (AR9170_PHY_REG_BASE + 0x041c)
#define AR9170_PHY_REG_RFBUS_GRANT (AR9170_PHY_REG_BASE + 0x0420)
#define AR9170_PHY_RFBUS_GRANT_EN 0x00000001
#define AR9170_PHY_REG_CHAN_INFO_GAIN_DIFF (AR9170_PHY_REG_BASE + 0x04f4)
#define AR9170_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
#define AR9170_PHY_REG_CHAN_INFO_GAIN (AR9170_PHY_REG_BASE + 0x04fc)
#define AR9170_PHY_REG_MODE (AR9170_PHY_REG_BASE + 0x0a00)
#define AR9170_PHY_MODE_ASYNCFIFO 0x80
#define AR9170_PHY_MODE_AR2133 0x08
#define AR9170_PHY_MODE_AR5111 0x00
#define AR9170_PHY_MODE_AR5112 0x08
#define AR9170_PHY_MODE_DYNAMIC 0x04
#define AR9170_PHY_MODE_RF2GHZ 0x02
#define AR9170_PHY_MODE_RF5GHZ 0x00
#define AR9170_PHY_MODE_CCK 0x01
#define AR9170_PHY_MODE_OFDM 0x00
#define AR9170_PHY_MODE_DYN_CCK_DISABLE 0x100
#define AR9170_PHY_REG_CCK_TX_CTRL (AR9170_PHY_REG_BASE + 0x0a04)
#define AR9170_PHY_CCK_TX_CTRL_JAPAN 0x00000010
#define AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000c
#define AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
#define AR9170_PHY_REG_CCK_DETECT (AR9170_PHY_REG_BASE + 0x0a08)
#define AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003f
#define AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
/* [12:6] settling time for antenna switch */
#define AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001fc0
#define AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
#define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
#define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
#define AR9170_PHY_REG_GAIN_2GHZ (AR9170_PHY_REG_BASE + 0x0a0c)
#define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c)
#define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00fc0000
#define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
#define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003c00
#define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
#define AR9170_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001f
#define AR9170_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
#define AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003e0000
#define AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17
#define AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001f000
#define AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12
#define AR9170_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000fc0
#define AR9170_PHY_GAIN_2GHZ_XATTEN2_DB_S 6
#define AR9170_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003f
#define AR9170_PHY_GAIN_2GHZ_XATTEN1_DB_S 0
#define AR9170_PHY_REG_CCK_RXCTRL4 (AR9170_PHY_REG_BASE + 0x0a1c)
#define AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01f80000
#define AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
#define AR9170_PHY_REG_DAG_CTRLCCK (AR9170_PHY_REG_BASE + 0x0a28)
#define AR9170_REG_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
#define AR9170_REG_DAG_CTRLCCK_RSSI_THR 0x0001fc00
#define AR9170_REG_DAG_CTRLCCK_RSSI_THR_S 10
#define AR9170_PHY_REG_FORCE_CLKEN_CCK (AR9170_PHY_REG_BASE + 0x0a2c)
#define AR9170_FORCE_CLKEN_CCK_MRC_MUX 0x00000040
#define AR9170_PHY_REG_POWER_TX_RATE3 (AR9170_PHY_REG_BASE + 0x0a34)
#define AR9170_PHY_REG_POWER_TX_RATE4 (AR9170_PHY_REG_BASE + 0x0a38)
#define AR9170_PHY_REG_SCRM_SEQ_XR (AR9170_PHY_REG_BASE + 0x0a3c)
#define AR9170_PHY_REG_HEADER_DETECT_XR (AR9170_PHY_REG_BASE + 0x0a40)
#define AR9170_PHY_REG_CHIRP_DETECTED_XR (AR9170_PHY_REG_BASE + 0x0a44)
#define AR9170_PHY_REG_BLUETOOTH (AR9170_PHY_REG_BASE + 0x0a54)
#define AR9170_PHY_REG_TPCRG1 (AR9170_PHY_REG_BASE + 0x0a58)
#define AR9170_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
#define AR9170_PHY_TPCRG1_NUM_PD_GAIN_S 14
#define AR9170_PHY_TPCRG1_PD_GAIN_1 0x00030000
#define AR9170_PHY_TPCRG1_PD_GAIN_1_S 16
#define AR9170_PHY_TPCRG1_PD_GAIN_2 0x000c0000
#define AR9170_PHY_TPCRG1_PD_GAIN_2_S 18
#define AR9170_PHY_TPCRG1_PD_GAIN_3 0x00300000
#define AR9170_PHY_TPCRG1_PD_GAIN_3_S 20
#define AR9170_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
#define AR9170_PHY_TPCRG1_PD_CAL_ENABLE_S 22
#define AR9170_PHY_REG_TX_PWRCTRL4 (AR9170_PHY_REG_BASE + 0x0a64)
#define AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
#define AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0
#define AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001fe
#define AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
#define AR9170_PHY_REG_ANALOG_SWAP (AR9170_PHY_REG_BASE + 0x0a68)
#define AR9170_PHY_ANALOG_SWAP_AB 0x0001
#define AR9170_PHY_ANALOG_SWAP_ALT_CHAIN 0x00000040
#define AR9170_PHY_REG_TPCRG5 (AR9170_PHY_REG_BASE + 0x0a6c)
#define AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000f
#define AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003f0
#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000fc00
#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003f0000
#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0fc00000
#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
#define AR9170_PHY_REG_TX_PWRCTRL6_0 (AR9170_PHY_REG_BASE + 0x0a70)
#define AR9170_PHY_REG_TX_PWRCTRL6_1 (AR9170_PHY_REG_BASE + 0x1a70)
#define AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000
#define AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
#define AR9170_PHY_REG_TX_PWRCTRL7 (AR9170_PHY_REG_BASE + 0x0a74)
#define AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01f80000
#define AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
#define AR9170_PHY_REG_TX_PWRCTRL9 (AR9170_PHY_REG_BASE + 0x0a7c)
#define AR9170_PHY_TX_DESIRED_SCALE_CCK 0x00007c00
#define AR9170_PHY_TX_DESIRED_SCALE_CCK_S 10
#define AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
#define AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31
#define AR9170_PHY_REG_TX_GAIN_TBL1 (AR9170_PHY_REG_BASE + 0x0b00)
#define AR9170_PHY_TX_GAIN 0x0007f000
#define AR9170_PHY_TX_GAIN_S 12
/* Carrier leak calibration control, do it after AGC calibration */
#define AR9170_PHY_REG_CL_CAL_CTL (AR9170_PHY_REG_BASE + 0x0b58)
#define AR9170_PHY_CL_CAL_ENABLE 0x00000002
#define AR9170_PHY_CL_CAL_PARALLEL_CAL_ENABLE 0x00000001
#define AR9170_PHY_REG_POWER_TX_RATE5 (AR9170_PHY_REG_BASE + 0x0b8c)
#define AR9170_PHY_REG_POWER_TX_RATE6 (AR9170_PHY_REG_BASE + 0x0b90)
#define AR9170_PHY_REG_CH0_TX_PWRCTRL11 (AR9170_PHY_REG_BASE + 0x0b98)
#define AR9170_PHY_REG_CH1_TX_PWRCTRL11 (AR9170_PHY_REG_BASE + 0x1b98)
#define AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP 0x0000fc00
#define AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP_S 10
#define AR9170_PHY_REG_CAL_CHAINMASK (AR9170_PHY_REG_BASE + 0x0b9c)
#define AR9170_PHY_REG_VIT_MASK2_M_46_61 (AR9170_PHY_REG_BASE + 0x0ba0)
#define AR9170_PHY_REG_MASK2_M_31_45 (AR9170_PHY_REG_BASE + 0x0ba4)
#define AR9170_PHY_REG_MASK2_M_16_30 (AR9170_PHY_REG_BASE + 0x0ba8)
#define AR9170_PHY_REG_MASK2_M_00_15 (AR9170_PHY_REG_BASE + 0x0bac)
#define AR9170_PHY_REG_PILOT_MASK_01_30 (AR9170_PHY_REG_BASE + 0x0bb0)
#define AR9170_PHY_REG_PILOT_MASK_31_60 (AR9170_PHY_REG_BASE + 0x0bb4)
#define AR9170_PHY_REG_MASK2_P_15_01 (AR9170_PHY_REG_BASE + 0x0bb8)
#define AR9170_PHY_REG_MASK2_P_30_16 (AR9170_PHY_REG_BASE + 0x0bbc)
#define AR9170_PHY_REG_MASK2_P_45_31 (AR9170_PHY_REG_BASE + 0x0bc0)
#define AR9170_PHY_REG_MASK2_P_61_45 (AR9170_PHY_REG_BASE + 0x0bc4)
#define AR9170_PHY_REG_POWER_TX_SUB (AR9170_PHY_REG_BASE + 0x0bc8)
#define AR9170_PHY_REG_POWER_TX_RATE7 (AR9170_PHY_REG_BASE + 0x0bcc)
#define AR9170_PHY_REG_POWER_TX_RATE8 (AR9170_PHY_REG_BASE + 0x0bd0)
#define AR9170_PHY_REG_POWER_TX_RATE9 (AR9170_PHY_REG_BASE + 0x0bd4)
#define AR9170_PHY_REG_XPA_CFG (AR9170_PHY_REG_BASE + 0x0bd8)
#define AR9170_PHY_FORCE_XPA_CFG 0x000000001
#define AR9170_PHY_FORCE_XPA_CFG_S 0
#define AR9170_PHY_REG_CH1_CCA (AR9170_PHY_REG_BASE + 0x1064)
#define AR9170_PHY_CH1_CCA_MIN_PWR 0x0ff80000
#define AR9170_PHY_CH1_CCA_MIN_PWR_S 19
#define AR9170_PHY_REG_CH2_CCA (AR9170_PHY_REG_BASE + 0x2064)
#define AR9170_PHY_CH2_CCA_MIN_PWR 0x0ff80000
#define AR9170_PHY_CH2_CCA_MIN_PWR_S 19
#define AR9170_PHY_REG_CH1_EXT_CCA (AR9170_PHY_REG_BASE + 0x11bc)
#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR 0xff800000
#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR_S 23
#define AR9170_PHY_REG_CH2_EXT_CCA (AR9170_PHY_REG_BASE + 0x21bc)
#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR 0xff800000
#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR_S 23
#endif /* __CARL9170_SHARED_PHY_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
#ifndef __CARL9170_SHARED_VERSION_H
#define __CARL9170_SHARED_VERSION_H
#define CARL9170FW_VERSION_YEAR 12
#define CARL9170FW_VERSION_MONTH 7
#define CARL9170FW_VERSION_DAY 7
#define CARL9170FW_VERSION_GIT "1.9.6"
#endif /* __CARL9170_SHARED_VERSION_H */

View File

@@ -0,0 +1,435 @@
/*
* Shared Atheros AR9170 Header
*
* RX/TX meta descriptor format
*
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, see
* http://www.gnu.org/licenses/.
*
* This file incorporates work covered by the following copyright and
* permission notice:
* Copyright (c) 2007-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or 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.
*/
#ifndef __CARL9170_SHARED_WLAN_H
#define __CARL9170_SHARED_WLAN_H
#include "fwcmd.h"
#define AR9170_RX_PHY_RATE_CCK_1M 0x0a
#define AR9170_RX_PHY_RATE_CCK_2M 0x14
#define AR9170_RX_PHY_RATE_CCK_5M 0x37
#define AR9170_RX_PHY_RATE_CCK_11M 0x6e
#define AR9170_ENC_ALG_NONE 0x0
#define AR9170_ENC_ALG_WEP64 0x1
#define AR9170_ENC_ALG_TKIP 0x2
#define AR9170_ENC_ALG_AESCCMP 0x4
#define AR9170_ENC_ALG_WEP128 0x5
#define AR9170_ENC_ALG_WEP256 0x6
#define AR9170_ENC_ALG_CENC 0x7
#define AR9170_RX_ENC_SOFTWARE 0x8
#define AR9170_RX_STATUS_MODULATION 0x03
#define AR9170_RX_STATUS_MODULATION_S 0
#define AR9170_RX_STATUS_MODULATION_CCK 0x00
#define AR9170_RX_STATUS_MODULATION_OFDM 0x01
#define AR9170_RX_STATUS_MODULATION_HT 0x02
#define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03
/* depends on modulation */
#define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08
#define AR9170_RX_STATUS_GREENFIELD 0x08
#define AR9170_RX_STATUS_MPDU 0x30
#define AR9170_RX_STATUS_MPDU_S 4
#define AR9170_RX_STATUS_MPDU_SINGLE 0x00
#define AR9170_RX_STATUS_MPDU_FIRST 0x20
#define AR9170_RX_STATUS_MPDU_MIDDLE 0x30
#define AR9170_RX_STATUS_MPDU_LAST 0x10
#define AR9170_RX_STATUS_CONT_AGGR 0x40
#define AR9170_RX_STATUS_TOTAL_ERROR 0x80
#define AR9170_RX_ERROR_RXTO 0x01
#define AR9170_RX_ERROR_OVERRUN 0x02
#define AR9170_RX_ERROR_DECRYPT 0x04
#define AR9170_RX_ERROR_FCS 0x08
#define AR9170_RX_ERROR_WRONG_RA 0x10
#define AR9170_RX_ERROR_PLCP 0x20
#define AR9170_RX_ERROR_MMIC 0x40
/* these are either-or */
#define AR9170_TX_MAC_PROT_RTS 0x0001
#define AR9170_TX_MAC_PROT_CTS 0x0002
#define AR9170_TX_MAC_PROT 0x0003
#define AR9170_TX_MAC_NO_ACK 0x0004
/* if unset, MAC will only do SIFS space before frame */
#define AR9170_TX_MAC_BACKOFF 0x0008
#define AR9170_TX_MAC_BURST 0x0010
#define AR9170_TX_MAC_AGGR 0x0020
/* encryption is a two-bit field */
#define AR9170_TX_MAC_ENCR_NONE 0x0000
#define AR9170_TX_MAC_ENCR_RC4 0x0040
#define AR9170_TX_MAC_ENCR_CENC 0x0080
#define AR9170_TX_MAC_ENCR_AES 0x00c0
#define AR9170_TX_MAC_MMIC 0x0100
#define AR9170_TX_MAC_HW_DURATION 0x0200
#define AR9170_TX_MAC_QOS_S 10
#define AR9170_TX_MAC_QOS 0x0c00
#define AR9170_TX_MAC_DISABLE_TXOP 0x1000
#define AR9170_TX_MAC_TXOP_RIFS 0x2000
#define AR9170_TX_MAC_IMM_BA 0x4000
/* either-or */
#define AR9170_TX_PHY_MOD_CCK 0x00000000
#define AR9170_TX_PHY_MOD_OFDM 0x00000001
#define AR9170_TX_PHY_MOD_HT 0x00000002
/* depends on modulation */
#define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004
#define AR9170_TX_PHY_GREENFIELD 0x00000004
#define AR9170_TX_PHY_BW_S 3
#define AR9170_TX_PHY_BW (3 << AR9170_TX_PHY_BW_SHIFT)
#define AR9170_TX_PHY_BW_20MHZ 0
#define AR9170_TX_PHY_BW_40MHZ 2
#define AR9170_TX_PHY_BW_40MHZ_DUP 3
#define AR9170_TX_PHY_TX_HEAVY_CLIP_S 6
#define AR9170_TX_PHY_TX_HEAVY_CLIP (7 << \
AR9170_TX_PHY_TX_HEAVY_CLIP_S)
#define AR9170_TX_PHY_TX_PWR_S 9
#define AR9170_TX_PHY_TX_PWR (0x3f << \
AR9170_TX_PHY_TX_PWR_S)
#define AR9170_TX_PHY_TXCHAIN_S 15
#define AR9170_TX_PHY_TXCHAIN (7 << \
AR9170_TX_PHY_TXCHAIN_S)
#define AR9170_TX_PHY_TXCHAIN_1 1
/* use for cck, ofdm 6/9/12/18/24 and HT if capable */
#define AR9170_TX_PHY_TXCHAIN_2 5
#define AR9170_TX_PHY_MCS_S 18
#define AR9170_TX_PHY_MCS (0x7f << \
AR9170_TX_PHY_MCS_S)
#define AR9170_TX_PHY_RATE_CCK_1M 0x0
#define AR9170_TX_PHY_RATE_CCK_2M 0x1
#define AR9170_TX_PHY_RATE_CCK_5M 0x2
#define AR9170_TX_PHY_RATE_CCK_11M 0x3
/* same as AR9170_RX_PHY_RATE */
#define AR9170_TXRX_PHY_RATE_OFDM_6M 0xb
#define AR9170_TXRX_PHY_RATE_OFDM_9M 0xf
#define AR9170_TXRX_PHY_RATE_OFDM_12M 0xa
#define AR9170_TXRX_PHY_RATE_OFDM_18M 0xe
#define AR9170_TXRX_PHY_RATE_OFDM_24M 0x9
#define AR9170_TXRX_PHY_RATE_OFDM_36M 0xd
#define AR9170_TXRX_PHY_RATE_OFDM_48M 0x8
#define AR9170_TXRX_PHY_RATE_OFDM_54M 0xc
#define AR9170_TXRX_PHY_RATE_HT_MCS0 0x0
#define AR9170_TXRX_PHY_RATE_HT_MCS1 0x1
#define AR9170_TXRX_PHY_RATE_HT_MCS2 0x2
#define AR9170_TXRX_PHY_RATE_HT_MCS3 0x3
#define AR9170_TXRX_PHY_RATE_HT_MCS4 0x4
#define AR9170_TXRX_PHY_RATE_HT_MCS5 0x5
#define AR9170_TXRX_PHY_RATE_HT_MCS6 0x6
#define AR9170_TXRX_PHY_RATE_HT_MCS7 0x7
#define AR9170_TXRX_PHY_RATE_HT_MCS8 0x8
#define AR9170_TXRX_PHY_RATE_HT_MCS9 0x9
#define AR9170_TXRX_PHY_RATE_HT_MCS10 0xa
#define AR9170_TXRX_PHY_RATE_HT_MCS11 0xb
#define AR9170_TXRX_PHY_RATE_HT_MCS12 0xc
#define AR9170_TXRX_PHY_RATE_HT_MCS13 0xd
#define AR9170_TXRX_PHY_RATE_HT_MCS14 0xe
#define AR9170_TXRX_PHY_RATE_HT_MCS15 0xf
#define AR9170_TX_PHY_SHORT_GI 0x80000000
#ifdef __CARL9170FW__
struct ar9170_tx_hw_mac_control {
union {
struct {
/*
* Beware of compiler bugs in all gcc pre 4.4!
*/
u8 erp_prot:2;
u8 no_ack:1;
u8 backoff:1;
u8 burst:1;
u8 ampdu:1;
u8 enc_mode:2;
u8 hw_mmic:1;
u8 hw_duration:1;
u8 qos_queue:2;
u8 disable_txop:1;
u8 txop_rifs:1;
u8 ba_end:1;
u8 probe:1;
} __packed;
__le16 set;
} __packed;
} __packed;
struct ar9170_tx_hw_phy_control {
union {
struct {
/*
* Beware of compiler bugs in all gcc pre 4.4!
*/
u8 modulation:2;
u8 preamble:1;
u8 bandwidth:2;
u8:1;
u8 heavy_clip:3;
u8 tx_power:6;
u8 chains:3;
u8 mcs:7;
u8:6;
u8 short_gi:1;
} __packed;
__le32 set;
} __packed;
} __packed;
struct ar9170_tx_rate_info {
u8 tries:3;
u8 erp_prot:2;
u8 ampdu:1;
u8 free:2; /* free for use (e.g.:RIFS/TXOP/AMPDU) */
} __packed;
struct carl9170_tx_superdesc {
__le16 len;
u8 rix;
u8 cnt;
u8 cookie;
u8 ampdu_density:3;
u8 ampdu_factor:2;
u8 ampdu_commit_density:1;
u8 ampdu_commit_factor:1;
u8 ampdu_unused_bit:1;
u8 queue:2;
u8 assign_seq:1;
u8 vif_id:3;
u8 fill_in_tsf:1;
u8 cab:1;
u8 padding2;
struct ar9170_tx_rate_info ri[CARL9170_TX_MAX_RATES];
struct ar9170_tx_hw_phy_control rr[CARL9170_TX_MAX_RETRY_RATES];
} __packed;
struct ar9170_tx_hwdesc {
__le16 length;
struct ar9170_tx_hw_mac_control mac;
struct ar9170_tx_hw_phy_control phy;
} __packed;
struct ar9170_tx_frame {
struct ar9170_tx_hwdesc hdr;
union {
struct ieee80211_hdr i3e;
u8 payload[0];
} data;
} __packed;
struct carl9170_tx_superframe {
struct carl9170_tx_superdesc s;
struct ar9170_tx_frame f;
} __packed __aligned(4);
#endif /* __CARL9170FW__ */
struct _ar9170_tx_hwdesc {
__le16 length;
__le16 mac_control;
__le32 phy_control;
} __packed;
#define CARL9170_TX_SUPER_AMPDU_DENSITY_S 0
#define CARL9170_TX_SUPER_AMPDU_DENSITY 0x7
#define CARL9170_TX_SUPER_AMPDU_FACTOR 0x18
#define CARL9170_TX_SUPER_AMPDU_FACTOR_S 3
#define CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY 0x20
#define CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY_S 5
#define CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR 0x40
#define CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR_S 6
#define CARL9170_TX_SUPER_MISC_QUEUE 0x3
#define CARL9170_TX_SUPER_MISC_QUEUE_S 0
#define CARL9170_TX_SUPER_MISC_ASSIGN_SEQ 0x4
#define CARL9170_TX_SUPER_MISC_VIF_ID 0x38
#define CARL9170_TX_SUPER_MISC_VIF_ID_S 3
#define CARL9170_TX_SUPER_MISC_FILL_IN_TSF 0x40
#define CARL9170_TX_SUPER_MISC_CAB 0x80
#define CARL9170_TX_SUPER_RI_TRIES 0x7
#define CARL9170_TX_SUPER_RI_TRIES_S 0
#define CARL9170_TX_SUPER_RI_ERP_PROT 0x18
#define CARL9170_TX_SUPER_RI_ERP_PROT_S 3
#define CARL9170_TX_SUPER_RI_AMPDU 0x20
#define CARL9170_TX_SUPER_RI_AMPDU_S 5
struct _carl9170_tx_superdesc {
__le16 len;
u8 rix;
u8 cnt;
u8 cookie;
u8 ampdu_settings;
u8 misc;
u8 padding;
u8 ri[CARL9170_TX_MAX_RATES];
__le32 rr[CARL9170_TX_MAX_RETRY_RATES];
} __packed;
struct _carl9170_tx_superframe {
struct _carl9170_tx_superdesc s;
struct _ar9170_tx_hwdesc f;
u8 frame_data[0];
} __packed __aligned(4);
#define CARL9170_TX_SUPERDESC_LEN 24
#define AR9170_TX_HWDESC_LEN 8
#define CARL9170_TX_SUPERFRAME_LEN (CARL9170_TX_SUPERDESC_LEN + \
AR9170_TX_HWDESC_LEN)
struct ar9170_rx_head {
u8 plcp[12];
} __packed;
#define AR9170_RX_HEAD_LEN 12
struct ar9170_rx_phystatus {
union {
struct {
u8 rssi_ant0, rssi_ant1, rssi_ant2,
rssi_ant0x, rssi_ant1x, rssi_ant2x,
rssi_combined;
} __packed;
u8 rssi[7];
} __packed;
u8 evm_stream0[6], evm_stream1[6];
u8 phy_err;
} __packed;
#define AR9170_RX_PHYSTATUS_LEN 20
struct ar9170_rx_macstatus {
u8 SAidx, DAidx;
u8 error;
u8 status;
} __packed;
#define AR9170_RX_MACSTATUS_LEN 4
struct ar9170_rx_frame_single {
struct ar9170_rx_head phy_head;
struct ieee80211_hdr i3e;
struct ar9170_rx_phystatus phy_tail;
struct ar9170_rx_macstatus macstatus;
} __packed;
struct ar9170_rx_frame_head {
struct ar9170_rx_head phy_head;
struct ieee80211_hdr i3e;
struct ar9170_rx_macstatus macstatus;
} __packed;
struct ar9170_rx_frame_middle {
struct ieee80211_hdr i3e;
struct ar9170_rx_macstatus macstatus;
} __packed;
struct ar9170_rx_frame_tail {
struct ieee80211_hdr i3e;
struct ar9170_rx_phystatus phy_tail;
struct ar9170_rx_macstatus macstatus;
} __packed;
struct ar9170_rx_frame {
union {
struct ar9170_rx_frame_single single;
struct ar9170_rx_frame_head head;
struct ar9170_rx_frame_middle middle;
struct ar9170_rx_frame_tail tail;
} __packed;
} __packed;
static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
{
return (t->SAidx & 0xc0) >> 4 |
(t->DAidx & 0xc0) >> 6;
}
/*
* This is an workaround for several undocumented bugs.
* Don't mess with the QoS/AC <-> HW Queue map, if you don't
* know what you are doing.
*
* Known problems [hardware]:
* * The MAC does not aggregate frames on anything other
* than the first HW queue.
* * when an AMPDU is placed [in the first hw queue] and
* additional frames are already queued on a different
* hw queue, the MAC will ALWAYS freeze.
*
* In a nutshell: The hardware can either do QoS or
* Aggregation but not both at the same time. As a
* result, this makes the device pretty much useless
* for any serious 802.11n setup.
*/
enum ar9170_txq {
AR9170_TXQ_BK = 0, /* TXQ0 */
AR9170_TXQ_BE, /* TXQ1 */
AR9170_TXQ_VI, /* TXQ2 */
AR9170_TXQ_VO, /* TXQ3 */
__AR9170_NUM_TXQ,
};
#define AR9170_TXQ_DEPTH 32
#endif /* __CARL9170_SHARED_WLAN_H */